<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:dcterms="http://purl.org/dc/terms/"
     xmlns:media="http://search.yahoo.com/mrss/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:cf="https://www.futureplc.com/rss/content-flags"
>
    <channel>
                    <atom:link href="https://www.tomsguide.com/feeds/tag/fitness" rel="self" type="application/rss+xml" />
                            <title><![CDATA[ Latest from Tom's Guide in Fitness ]]></title>
                <link>https://www.tomsguide.com/wellness/fitness</link>
        <description><![CDATA[ All the latest fitness content from the Tom's Guide team ]]></description>
                                    <lastBuildDate>Sat, 31 Oct 2026 04:30:00 +0000</lastBuildDate>
                            <language>en</language>
                                <item>
                                                            <title><![CDATA[ Jessica Alba’s trainer says these 3 simple tests can reveal how well you’re aging – at 44, I tried them all ]]></title>
                                                                                                <dc:content><![CDATA[ <p>At 64, celebrity trainer <a href="https://www.instagram.com/ramonabraganza?utm_source=ig_web_button_share_sheet&amp;cplk=ZDNlZDc0MzIxNw==" target="_blank" rel="nofollow">Ramona Braganza</a> is seriously inspiring and strong. Scroll through her Instagram, and you’ll find her lifting weights, practicing pull-ups, hiking through Beverly Hills and generally doing all the things I hope I’m still doing 20 years from now. </p><p>Braganza has spent decades training some of Hollywood’s biggest names, including Jessica Alba, Halle Berry and Zac Efron, but these days, her own training has a slightly different focus: longevity. </p><p>“Never underestimate the power of a strong body to help build a strong life,” says Braganza, who once graced the cover of Muscle &amp; Fitness magazine and regularly shares her own workouts alongside training her 91-year-old mum and clients.</p><p>Which brings me to Braganza's three simple tests of strength, balance and functional fitness. No fancy equipment, lab testing, or expensive longevity assessment is involved. In fact, you can do all three at home in a matter of minutes.</p><p>Naturally, I wanted to see how I measured up.</p><h3 class="article-body__section" id="section-why-does-it-matter"><span>Why does it matter?</span></h3><p>“Staying healthy isn’t about doing everything perfectly,” she says. “It’s about paying attention, making adjustments, being consistent and working with your body as it changes.”</p><p>Braganza's own formula isn't particularly complicated: walk, lift progressively, keep getting stronger, watch your sugar intake and, most importantly, keep showing up.</p><p>“We can’t always control our genetics, but we can control many of the choices we make around them,” she says.</p><p>At 44, this really resonates with me. I've already noticed my reasons for training starting to change. Yes, I still want muscle and definition, but I'm increasingly interested in how my body feels when I run, lift, and stretch, and I'm adamant I want to still be doing these things in another 20, 30, or even 40 years.</p><h2 id="3-longevity-tests">3 longevity tests</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/Dey8T0lz1m6/" target="_blank">A post shared by Tom's Guide Fitness | Workout Tips &amp; Gear (@tomsguidefitness)</a></p><p>A photo posted by </p></blockquote></div><h2 class="article-body__section" id="section-1-sit-to-stand"><span>1. Sit to stand</span></h2><p>First up is something most of us do multiple times a day without thinking about it: we sit down, then stand back up again.</p><p>For the test, Braganza recommends setting a timer for 30 seconds and seeing how many complete reps you can perform. Her benchmark for women over 60 is 15 or more.</p><p>It sounds ridiculously easy. But repeatedly getting yourself out of a chair without using your hands calls on your leg and core strength, mobility, balance and control, which are all things that become increasingly important as we get older. </p><p>And there’s evidence that suggests how well you perform could tell something about healthy aging, too. A <a href="https://pubmed.ncbi.nlm.nih.gov/42570528/" target="_blank">2026 study</a> that followed 2,747 older adults for 15 years found that poorer chair-stand performance was associated with a 36% higher risk of death from any cause.</p><p><strong>How I got on</strong>: 18 reps for me, which is probably about right considering I’m 16 years off 60.</p><h3 class="article-body__section" id="section-2-single-leg-balance"><span>2. Single-leg balance</span></h3><p>Next up, stand on one leg and start the clock. Braganza considers 30 seconds or more an excellent result.</p><p>Balance is one of those things I rarely think about. I run, lift weights and do yoga, so I just assume mine is pretty good. But your ability to stabilize yourself becomes increasingly important as you get older, particularly when it comes to navigating stairs, uneven ground and everyday movements. Good balance can also help reduce the risk of falls and keep you moving confidently as you age.</p><p><strong>How I got on</strong>: 30 seconds on each leg with no wobble. There’s good reason to keep an eye on your balance as you get older. A <a href="https://bjsm.bmj.com/content/56/17/975" target="_blank">study</a> in the British Journal of Sports Medicine found that adults aged 51 to 75 who couldn’t balance on one leg for 10 seconds had an 84% higher risk of all-cause mortality during the follow-up period.</p><h3 class="article-body__section" id="section-3-dead-hang"><span>3. Dead hang</span></h3><p>Finally, it was time to hit the pull-up bar and hang on for as long as possible.</p><p>Braganza gives 30–60 seconds as a strong goal, and this was probably the test I was most intrigued by. Hanging from a bar looks easy right up until your forearms start burning and your fingers begin peeling away from the bar.</p><p>The dead hang tests grip and upper-body strength, and grip strength has attracted plenty of attention in longevity research because of its association with health and physical function as you age.</p><p><strong>How I got on</strong>: I managed just under 90 seconds and that was at the end of a push session, so my hands definitely gave up before my forearms.</p><p>Of course, a dead hang isn't quite the same as a clinical grip-strength test, but there's good reason to pay attention to your grip. <a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC9178163/?utm_source=chatgpt.com" target="_blank">Research</a> has linked lower handgrip strength with an increased risk of premature death, making it another useful indicator of your health as you age.</p><h2 id="am-i-aging-well-at-44">Am I aging well at 44?</h2><div><blockquote><p>Longevity isn’t just about adding years to your life. It’s about adding life to your years.</p></blockquote></div><p>After doing all three tests, I'm happy to say I'm doing OK, and it's reassuring to know that the training I'm doing now is helping me build the strength and fitness I want to carry into later life.</p><p>I'm a big believer in “use it or lose it,” and I have absolutely no intention of letting the little old lady in me out any earlier than necessary. So I'll continue with my two to three resistance-training sessions a week, one yoga session and two to three runs, mixing hill sprints with longer Zone 2 sessions.</p><p>Like Braganza, I feel as though I'm starting to train for the second half of my life. I'm not only training for the body I have now, but also for the one I want in 20 or 30 years. </p><p>“Longevity isn’t just about adding years to your life. It’s about adding life to your years,” says Braganza. And I’m inclined to agree.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OKB5GW"></div>                            </div>                            <script src="https://kwizly.com/embed/OKB5GW.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/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> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/workouts/jessica-albas-trainer-says-these-3-simple-tests-can-reveal-how-well-youre-aging-at-44-i-tried-them-all</link>
                                                                            <description>
                            <![CDATA[ Forget expensive longevity tests. Celebrity trainer Ramona Braganza uses three simple exercises to test your strength, balance and mobility, and you can try them at home. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">TEp4GJUY66T5HBcbPoDFYL</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/ZKi7pvJjxioEGMqdqiggrj-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 31 Oct 2026 04:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Workouts]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Lucy Miller ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/s9KatBYrBQVZzj5oPAagPM-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Lucy Miller&amp;nbsp;is a Journalist, Level 3 Personal Trainer, Nutritional Advisor and Children’s Fitness Specialist. She holds fitness qualifications from NASM Training and Premier Training International and has been a fitness journalist and model for over 20 years. Since going freelance in 2014, Lucy left Men’s Fitness Magazine to write for an abundance of top consumer titles such as Women’s Health, Women’s Fitness, Glamour, Top Sante, The Guardian and Runners World.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;She’s also extremely passionate when it comes to educating others about health and physical activity and loves inspiring and working with children and adults to help make fitness fun, sustainable and accessible.&amp;nbsp;In her spare time, Lucy is ever the sportswoman. Once a national gymnast, having won three national titles, she has also run a handful of marathons around the world and loves to test her physical and metal side with regular running and gym sessions, not to mention ballet, bootcamp, boxing and TRX.&amp;nbsp;&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/ZKi7pvJjxioEGMqdqiggrj-1920-80.jpg">
                                                            <media:credit><![CDATA[Ramona Braganza/Lucy Miller/Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Left, Ramona performing bicep curl seated and smiling, right, Lucy doing sit to squat test in park]]></media:description>                                                            <media:text><![CDATA[Left, Ramona performing bicep curl seated and smiling, right, Lucy doing sit to squat test in park]]></media:text>
                                <media:title type="plain"><![CDATA[Left, Ramona performing bicep curl seated and smiling, right, Lucy doing sit to squat test in park]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/ZKi7pvJjxioEGMqdqiggrj-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>At 64, celebrity trainer <a href="https://www.instagram.com/ramonabraganza?utm_source=ig_web_button_share_sheet&amp;cplk=ZDNlZDc0MzIxNw==" target="_blank" rel="nofollow">Ramona Braganza</a> is seriously inspiring and strong. Scroll through her Instagram, and you’ll find her lifting weights, practicing pull-ups, hiking through Beverly Hills and generally doing all the things I hope I’m still doing 20 years from now. </p><p>Braganza has spent decades training some of Hollywood’s biggest names, including Jessica Alba, Halle Berry and Zac Efron, but these days, her own training has a slightly different focus: longevity. </p><p>“Never underestimate the power of a strong body to help build a strong life,” says Braganza, who once graced the cover of Muscle &amp; Fitness magazine and regularly shares her own workouts alongside training her 91-year-old mum and clients.</p><p>Which brings me to Braganza's three simple tests of strength, balance and functional fitness. No fancy equipment, lab testing, or expensive longevity assessment is involved. In fact, you can do all three at home in a matter of minutes.</p><p>Naturally, I wanted to see how I measured up.</p><h3 class="article-body__section" id="section-why-does-it-matter"><span>Why does it matter?</span></h3><p>“Staying healthy isn’t about doing everything perfectly,” she says. “It’s about paying attention, making adjustments, being consistent and working with your body as it changes.”</p><p>Braganza's own formula isn't particularly complicated: walk, lift progressively, keep getting stronger, watch your sugar intake and, most importantly, keep showing up.</p><p>“We can’t always control our genetics, but we can control many of the choices we make around them,” she says.</p><p>At 44, this really resonates with me. I've already noticed my reasons for training starting to change. Yes, I still want muscle and definition, but I'm increasingly interested in how my body feels when I run, lift, and stretch, and I'm adamant I want to still be doing these things in another 20, 30, or even 40 years.</p><h2 id="3-longevity-tests">3 longevity tests</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/Dey8T0lz1m6/" target="_blank">A post shared by Tom's Guide Fitness | Workout Tips &amp; Gear (@tomsguidefitness)</a></p><p>A photo posted by </p></blockquote></div><h2 class="article-body__section" id="section-1-sit-to-stand"><span>1. Sit to stand</span></h2><p>First up is something most of us do multiple times a day without thinking about it: we sit down, then stand back up again.</p><p>For the test, Braganza recommends setting a timer for 30 seconds and seeing how many complete reps you can perform. Her benchmark for women over 60 is 15 or more.</p><p>It sounds ridiculously easy. But repeatedly getting yourself out of a chair without using your hands calls on your leg and core strength, mobility, balance and control, which are all things that become increasingly important as we get older. </p><p>And there’s evidence that suggests how well you perform could tell something about healthy aging, too. A <a href="https://pubmed.ncbi.nlm.nih.gov/42570528/" target="_blank">2026 study</a> that followed 2,747 older adults for 15 years found that poorer chair-stand performance was associated with a 36% higher risk of death from any cause.</p><p><strong>How I got on</strong>: 18 reps for me, which is probably about right considering I’m 16 years off 60.</p><h3 class="article-body__section" id="section-2-single-leg-balance"><span>2. Single-leg balance</span></h3><p>Next up, stand on one leg and start the clock. Braganza considers 30 seconds or more an excellent result.</p><p>Balance is one of those things I rarely think about. I run, lift weights and do yoga, so I just assume mine is pretty good. But your ability to stabilize yourself becomes increasingly important as you get older, particularly when it comes to navigating stairs, uneven ground and everyday movements. Good balance can also help reduce the risk of falls and keep you moving confidently as you age.</p><p><strong>How I got on</strong>: 30 seconds on each leg with no wobble. There’s good reason to keep an eye on your balance as you get older. A <a href="https://bjsm.bmj.com/content/56/17/975" target="_blank">study</a> in the British Journal of Sports Medicine found that adults aged 51 to 75 who couldn’t balance on one leg for 10 seconds had an 84% higher risk of all-cause mortality during the follow-up period.</p><h3 class="article-body__section" id="section-3-dead-hang"><span>3. Dead hang</span></h3><p>Finally, it was time to hit the pull-up bar and hang on for as long as possible.</p><p>Braganza gives 30–60 seconds as a strong goal, and this was probably the test I was most intrigued by. Hanging from a bar looks easy right up until your forearms start burning and your fingers begin peeling away from the bar.</p><p>The dead hang tests grip and upper-body strength, and grip strength has attracted plenty of attention in longevity research because of its association with health and physical function as you age.</p><p><strong>How I got on</strong>: I managed just under 90 seconds and that was at the end of a push session, so my hands definitely gave up before my forearms.</p><p>Of course, a dead hang isn't quite the same as a clinical grip-strength test, but there's good reason to pay attention to your grip. <a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC9178163/?utm_source=chatgpt.com" target="_blank">Research</a> has linked lower handgrip strength with an increased risk of premature death, making it another useful indicator of your health as you age.</p><h2 id="am-i-aging-well-at-44">Am I aging well at 44?</h2><div><blockquote><p>Longevity isn’t just about adding years to your life. It’s about adding life to your years.</p></blockquote></div><p>After doing all three tests, I'm happy to say I'm doing OK, and it's reassuring to know that the training I'm doing now is helping me build the strength and fitness I want to carry into later life.</p><p>I'm a big believer in “use it or lose it,” and I have absolutely no intention of letting the little old lady in me out any earlier than necessary. So I'll continue with my two to three resistance-training sessions a week, one yoga session and two to three runs, mixing hill sprints with longer Zone 2 sessions.</p><p>Like Braganza, I feel as though I'm starting to train for the second half of my life. I'm not only training for the body I have now, but also for the one I want in 20 or 30 years. </p><p>“Longevity isn’t just about adding years to your life. It’s about adding life to your years,” says Braganza. And I’m inclined to agree.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OKB5GW"></div>                            </div>                            <script src="https://kwizly.com/embed/OKB5GW.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/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[ 21 best fall jacketand fleece deals to shopbefore Black Friday — up to 50% off The North Face, Patagonia and more ]]></title>
                                                                                                <dc:content><![CDATA[ <p>With temperatures dropping and inclement weather just around the corner, now’s the perfect time to give your jacket and fleece lineup an upgrade. And luckily, you've come to the right place — we're already spotting tons of deals ahead of Black Friday, which means you can bundle up for less. </p><p>Retailers like Amazon and REI are slashing the prices on best-selling styles from Patagonia, The North Face, Carhartt and more. From affordable options under $50 to premium picks that are worth the splurge, there’s something for every budget. </p><p>If you're ready to grab some new layers for fall, keep scrolling to check out my favorite jacket and fleece deals to shop before Black Friday rolls around. </p><p><strong>Note: </strong>Prices may vary depending on the size and color you select (particularly on Amazon). Check out any different color options available in your size to find the best deals.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><strong></strong><a href="https://www.amazon.com/deals/?" target="_blank" rel="nofollow"><strong>shop all Amazon deals</strong></a></li><li><strong></strong><a href="https://www.rei.com/f/scd-deals" target="_blank" rel="nofollow"><strong>shop all REI deals</strong></a></li><li><strong>Columbia Glennaker Lake II Rain Jacket (Men's): </strong><a href="https://www.amazon.com/Columbia-Glennaker-Jacket-Black-Large/dp/B0CLR8QXKW" target="_blank" rel="nofollow"><strong>was $70 now $42</strong></a></li><li><strong>Carhartt Force Relaxed Fit Full-Zip Long-Sleeve (Men's): </strong><a href="https://www.amazon.com/dp/B0DMTFDTC7?" target="_blank" rel="nofollow"><strong>was $84 now $44</strong></a></li><li><strong>Columbia Switchback Jacket (Women's): </strong><a href="https://www.amazon.com/dp/B0CLR14KFG?" target="_blank" rel="nofollow"><strong>was $70 now $44</strong></a></li><li><strong>Carhartt Rain Defender Packable Anorak (Women's): </strong><a href="https://www.amazon.com/Carhartt-Defender-Lightweight-Packable-Asphalt/dp/B0DK5SZKCN?" target="_blank" rel="nofollow"><strong>was $79 now $49</strong></a></li><li><strong>The North Face Antora Jacket (Women's): </strong><a href="https://www.amazon.com/North-Face-Waterproof-Windproof-Adjustable/dp/B0F97WG8SQ?" target="_blank" rel="nofollow"><strong>was $130 now $91</strong></a></li><li><strong>Patagonia Houdini Half-Zip (Men's): </strong><a href="https://www.rei.com/product/228564/patagonia-houdini-stash-half-zip-jacket-mens?color=CASCADE%2520GREEN" target="_blank" rel="nofollow"><strong>was $139 now $100</strong></a></li><li><strong>Arc'teryx Squamish Hoody (Men's): </strong><a href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow"><strong>was $200 now $119</strong></a></li><li><strong>The North Face Aconcagua 3 Jacket (Men's): </strong><a href="https://www.amazon.com/dp/B0CNBVC6HQ?" target="_blank" rel="nofollow"><strong>was $220 now $134</strong></a></li></ul><h3 class="article-body__section" id="section-men-s-jacket-deals"><span>Men's Jacket Deals</span></h3><div class="product"><a data-dimension112="ac5c8938-d472-11f1-855d-39a681cafec4" data-action="Deal Block" data-label="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension48="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension25="$44" href="https://www.amazon.com/dp/B0DMTFDTC7?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:594px;"><p class="vanilla-image-block" style="padding-top:168.18%;"><img id="XVAtjBrciTnPeT2AD3fLvm" name="Long Sleeve Full zip" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XVAtjBrciTnPeT2AD3fLvm-1920-80.jpg" mos="" align="middle" fullscreen="" width="594" height="999" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0DMTFDTC7?" target="_blank" rel="nofollow" data-dimension112="ac5c8938-d472-11f1-855d-39a681cafec4" data-action="Deal Block" data-label="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension48="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension25="$44">Force Relaxed Fit Full-Zip Long-Sleeve (Men's): was $84 now $44</a></strong><br />Perfect for a casual stroll, low-intensity workout or a longer run, this versatile layer features Carhartt Force technology to wick sweat, dry fast, and fight odors. It's a full zip and allows for a full range of motion too. <a class="view-deal button" href="https://www.amazon.com/dp/B0DMTFDTC7?" target="_blank" rel="nofollow" data-dimension112="ac5c8938-d472-11f1-855d-39a681cafec4" data-action="Deal Block" data-label="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension48="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension25="$44">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c89b0-d472-11f1-8c92-1dfc0007624b" data-action="Deal Block" data-label="Glennaker Lake II Rain Jacket (Men's)" data-dimension48="Glennaker Lake II Rain Jacket (Men's)" data-dimension25="$42" href="https://www.amazon.com/Columbia-Glennaker-Jacket-Black-Large/dp/B0CLR8QXKW" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1105px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="Gp4VGe8Q8YaFDrascG72q" name="Columbia-m-glennaker" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Gp4VGe8Q8YaFDrascG72q-1920-80.jpg" mos="" align="middle" fullscreen="" width="1105" height="1105" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Columbia-Glennaker-Jacket-Black-Large/dp/B0CLR8QXKW" target="_blank" rel="nofollow" data-dimension112="ac5c89b0-d472-11f1-8c92-1dfc0007624b" data-action="Deal Block" data-label="Glennaker Lake II Rain Jacket (Men's)" data-dimension48="Glennaker Lake II Rain Jacket (Men's)" data-dimension25="$42">Glennaker Lake II Rain Jacket (Men's): was $70 now $42</a></strong><br />Need an affordable just-in-case rain jacket? Look no further than the Columbia Glennaker Lake. Made from 100% nylon, it features a stow-away hood that folds into the collar, zippered hand pockets, elastic cuffs and an adjustable hem. It's also small and light enough to shove inside a backpack or purse.<a class="view-deal button" href="https://www.amazon.com/Columbia-Glennaker-Jacket-Black-Large/dp/B0CLR8QXKW" target="_blank" rel="nofollow" data-dimension112="ac5c89b0-d472-11f1-8c92-1dfc0007624b" data-action="Deal Block" data-label="Glennaker Lake II Rain Jacket (Men's)" data-dimension48="Glennaker Lake II Rain Jacket (Men's)" data-dimension25="$42">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c8a28-d472-11f1-b575-f7676b82071a" data-action="Deal Block" data-label="Steens Mountain Full Zip 2.0 (Men's)" data-dimension48="Steens Mountain Full Zip 2.0 (Men's)" data-dimension25="$34" href="https://www.amazon.com/dp/B0FYJJTZJY?" 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:155.96%;"><img id="Bv68Qo72tT3oKtVBP7Czii" name="Columbia Fleece.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Bv68Qo72tT3oKtVBP7Czii-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1059" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0FYJJTZJY?" target="_blank" rel="nofollow" data-dimension112="ac5c8a28-d472-11f1-b575-f7676b82071a" data-action="Deal Block" data-label="Steens Mountain Full Zip 2.0 (Men's)" data-dimension48="Steens Mountain Full Zip 2.0 (Men's)" data-dimension25="$34">Steens Mountain Full Zip 2.0 (Men's): was $65 now $34</a></strong><br />The perfect grab and go zip up, this jacket is made of soft polyester fleece fabric and will keep you warm as the temperatures drop. Available in several different colors, it will definitely be an outdoor staple this fall. <a class="view-deal button" href="https://www.amazon.com/dp/B0FYJJTZJY?" target="_blank" rel="nofollow" data-dimension112="ac5c8a28-d472-11f1-b575-f7676b82071a" data-action="Deal Block" data-label="Steens Mountain Full Zip 2.0 (Men's)" data-dimension48="Steens Mountain Full Zip 2.0 (Men's)" data-dimension25="$34">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c8aa0-d472-11f1-80ce-a71a8d70af53" data-action="Deal Block" data-label="Ascender Softshell Rain Jacket (Men's)" data-dimension48="Ascender Softshell Rain Jacket (Men's)" data-dimension25="$49" href="https://www.amazon.com/dp/B0CLRBK7P2?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:829px;"><p class="vanilla-image-block" style="padding-top:100.12%;"><img id="RxbCzBdr6qyZyeYxwMo4jE" name="Columbia-m-ascender" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/RxbCzBdr6qyZyeYxwMo4jE-1920-80.jpg" mos="" align="middle" fullscreen="" width="829" height="830" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0CLRBK7P2?" target="_blank" rel="nofollow" data-dimension112="ac5c8aa0-d472-11f1-80ce-a71a8d70af53" data-action="Deal Block" data-label="Ascender Softshell Rain Jacket (Men's)" data-dimension48="Ascender Softshell Rain Jacket (Men's)" data-dimension25="$49">Ascender Softshell Rain Jacket (Men's): was $125 now $49</a></strong><br />This stretchy, chic softshell isn't for torrential downpours but will keep you dry in light rain and drizzle. Made from 100% polyester, it features zippered hand and chest pockets, an abrasion-resistant chin guard and an adjustable hem and cuffs. <a class="view-deal button" href="https://www.amazon.com/dp/B0CLRBK7P2?" target="_blank" rel="nofollow" data-dimension112="ac5c8aa0-d472-11f1-80ce-a71a8d70af53" data-action="Deal Block" data-label="Ascender Softshell Rain Jacket (Men's)" data-dimension48="Ascender Softshell Rain Jacket (Men's)" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c8b18-d472-11f1-bb3f-a9ba4ca78788" data-action="Deal Block" data-label="Rain Defender Jacket (Men's)" data-dimension48="Rain Defender Jacket (Men's)" data-dimension25="$74" href="https://www.amazon.com/Carhartt-Defender-Relaxed-Jacket-Ocean/dp/B0F8PLPT7B?" 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:127.84%;"><img id="VVpm8JrkWovdG4VCm3q4We" name="Rain Defender Jacket (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/VVpm8JrkWovdG4VCm3q4We-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="868" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Carhartt-Defender-Relaxed-Jacket-Ocean/dp/B0F8PLPT7B?" target="_blank" rel="nofollow" data-dimension112="ac5c8b18-d472-11f1-bb3f-a9ba4ca78788" data-action="Deal Block" data-label="Rain Defender Jacket (Men's)" data-dimension48="Rain Defender Jacket (Men's)" data-dimension25="$74">Rain Defender Jacket (Men's): was $99 now $74</a></strong><br />The Carhartt Rain Defender Jacket is now on sale from $74. It's perfect to take on wind and rain, while keeping you warm and dry. It's durable and moves with you thanks to its Rugged Flex stretch technology.<a class="view-deal button" href="https://www.amazon.com/Carhartt-Defender-Relaxed-Jacket-Ocean/dp/B0F8PLPT7B?" target="_blank" rel="nofollow" data-dimension112="ac5c8b18-d472-11f1-bb3f-a9ba4ca78788" data-action="Deal Block" data-label="Rain Defender Jacket (Men's)" data-dimension48="Rain Defender Jacket (Men's)" data-dimension25="$74">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c8b90-d472-11f1-b2aa-c1c978bc623a" data-action="Deal Block" data-label="Fleece Pullover (Men's)" data-dimension48="Fleece Pullover (Men's)" data-dimension25="$79" href="https://www.amazon.com/Carhartt-Loose-Fleece-Pullover-Oatmeal/dp/B0CR1X544H" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:658px;"><p class="vanilla-image-block" style="padding-top:151.82%;"><img id="cmnpDDU8xQkc4aDsdWRj3d" name="Carhartt fleece" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/cmnpDDU8xQkc4aDsdWRj3d-1920-80.jpg" mos="" align="middle" fullscreen="" width="658" height="999" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Carhartt-Loose-Fleece-Pullover-Oatmeal/dp/B0CR1X544H" target="_blank" rel="nofollow" data-dimension112="ac5c8b90-d472-11f1-b2aa-c1c978bc623a" data-action="Deal Block" data-label="Fleece Pullover (Men's)" data-dimension48="Fleece Pullover (Men's)" data-dimension25="$79">Fleece Pullover (Men's): was $99 now $79</a></strong><br />If you're looking for a pullover that feels like a warm hug, this is the one! The cozy quarter zip is the perfect layer for fall and features a loose fit for extra comfort. <a class="view-deal button" href="https://www.amazon.com/Carhartt-Loose-Fleece-Pullover-Oatmeal/dp/B0CR1X544H" target="_blank" rel="nofollow" data-dimension112="ac5c8b90-d472-11f1-b2aa-c1c978bc623a" data-action="Deal Block" data-label="Fleece Pullover (Men's)" data-dimension48="Fleece Pullover (Men's)" data-dimension25="$79">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c8c08-d472-11f1-84ef-17d33ce6716f" data-action="Deal Block" data-label="Powder Lite II Jacket (Men's)" data-dimension48="Powder Lite II Jacket (Men's)" data-dimension25="$99" href="https://www.amazon.com/Columbia-Powder-Jacket-Black-Large/dp/B0CLRBRZHS" 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:189.84%;"><img id="BtaCy7tDVwYLGzNAQeJusG" name="Powder Lite II Jacket (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/BtaCy7tDVwYLGzNAQeJusG-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1289" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Columbia-Powder-Jacket-Black-Large/dp/B0CLRBRZHS" target="_blank" rel="nofollow" data-dimension112="ac5c8c08-d472-11f1-84ef-17d33ce6716f" data-action="Deal Block" data-label="Powder Lite II Jacket (Men's)" data-dimension48="Powder Lite II Jacket (Men's)" data-dimension25="$99">Powder Lite II Jacket (Men's): was $165 now $99</a></strong><br />Columbia’s Omni-Heat thermal-reflective lining retains your body's own warmth, and the puffer also has a water-resistant outer layer for wet weather. Plus, it stows easily and is super lightweight if you enjoy hiking.<a class="view-deal button" href="https://www.amazon.com/Columbia-Powder-Jacket-Black-Large/dp/B0CLRBRZHS" target="_blank" rel="nofollow" data-dimension112="ac5c8c08-d472-11f1-84ef-17d33ce6716f" data-action="Deal Block" data-label="Powder Lite II Jacket (Men's)" data-dimension48="Powder Lite II Jacket (Men's)" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c8c80-d472-11f1-b21a-139d9f5a7dfb" data-action="Deal Block" data-label="Houdini Half-Zip (Men's)" data-dimension48="Houdini Half-Zip (Men's)" data-dimension25="$100" href="https://www.rei.com/product/228564/patagonia-houdini-stash-half-zip-jacket-mens?color=CASCADE%2520GREEN" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1090px;"><p class="vanilla-image-block" style="padding-top:112.75%;"><img id="Ae9C3N28VXVi824kshL69a" name="Screenshot 2026-06-15 at 9.10.35 PM" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Ae9C3N28VXVi824kshL69a-1920-80.png" mos="" align="middle" fullscreen="" width="1090" height="1229" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/228564/patagonia-houdini-stash-half-zip-jacket-mens?color=CASCADE%2520GREEN" target="_blank" rel="nofollow" data-dimension112="ac5c8c80-d472-11f1-b21a-139d9f5a7dfb" data-action="Deal Block" data-label="Houdini Half-Zip (Men's)" data-dimension48="Houdini Half-Zip (Men's)" data-dimension25="$100">Houdini Half-Zip (Men's): was $139 now $100</a></strong><br />The Patagonia Houdini Half-Zip is nothing short of pure magic. This back-pocket-packable pull-over weighs about as much as a deck of playing cards, yet offers seriously solid protection from the rain, wind and chill.<a class="view-deal button" href="https://www.rei.com/product/228564/patagonia-houdini-stash-half-zip-jacket-mens?color=CASCADE%2520GREEN" target="_blank" rel="nofollow" data-dimension112="ac5c8c80-d472-11f1-b21a-139d9f5a7dfb" data-action="Deal Block" data-label="Houdini Half-Zip (Men's)" data-dimension48="Houdini Half-Zip (Men's)" data-dimension25="$100">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c8e1a-d472-11f1-8706-914af691c77a" data-action="Deal Block" data-label="Squamish Hoody (Men's)" data-dimension48="Squamish Hoody (Men's)" data-dimension25="$119" href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="gU2HZNV4QV8x48bVFDMoVL" name="Arc'teryx Squamish" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gU2HZNV4QV8x48bVFDMoVL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow" data-dimension112="ac5c8e1a-d472-11f1-8706-914af691c77a" data-action="Deal Block" data-label="Squamish Hoody (Men's)" data-dimension48="Squamish Hoody (Men's)" data-dimension25="$119">Squamish Hoody (Men's): was $200 now $119</a></strong><br />The Arc'teryx Squamish Hoody is completely windproof and finished with DWR, making it a versatile outer layer for those nippy wintry hikes. There's even a capped hood for keeping your face dry. There are currently six colors discounted at varying price points. <a class="view-deal button" href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow" data-dimension112="ac5c8e1a-d472-11f1-8706-914af691c77a" data-action="Deal Block" data-label="Squamish Hoody (Men's)" data-dimension48="Squamish Hoody (Men's)" data-dimension25="$119">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c8eba-d472-11f1-bbb5-9bf2db6ffbb3" data-action="Deal Block" data-label="Daily Snap-T Pullover (Men's)" data-dimension48="Daily Snap-T Pullover (Men's)" data-dimension25="$124" href="https://www.rei.com/product/C01345/patagonia-daily-snap-t-pullover-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1560px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="WGXNCXSCXiBba8uzoeFYnS" name="Patagonia Snap T" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/WGXNCXSCXiBba8uzoeFYnS-1920-80.jpg" mos="" align="middle" fullscreen="" width="1560" height="1560" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01345/patagonia-daily-snap-t-pullover-mens" target="_blank" rel="nofollow" data-dimension112="ac5c8eba-d472-11f1-bbb5-9bf2db6ffbb3" data-action="Deal Block" data-label="Daily Snap-T Pullover (Men's)" data-dimension48="Daily Snap-T Pullover (Men's)" data-dimension25="$124">Daily Snap-T Pullover (Men's): was $179 now $124</a></strong><br />This is the same as the deal listed above, except it's the men's version. It's available in nearly every single size in three different colors, so you'll be able to find your perfect fit. <a class="view-deal button" href="https://www.rei.com/product/C01345/patagonia-daily-snap-t-pullover-mens" target="_blank" rel="nofollow" data-dimension112="ac5c8eba-d472-11f1-bbb5-9bf2db6ffbb3" data-action="Deal Block" data-label="Daily Snap-T Pullover (Men's)" data-dimension48="Daily Snap-T Pullover (Men's)" data-dimension25="$124">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c8faa-d472-11f1-bf3a-139468c5b582" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$134" href="https://www.amazon.com/dp/B0CNBVC6HQ?" 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:187.78%;"><img id="jLN4YbW223nKsxQxPVPWZR" name="TNF jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jLN4YbW223nKsxQxPVPWZR-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1275" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0CNBVC6HQ?" target="_blank" rel="nofollow" data-dimension112="ac5c8faa-d472-11f1-bf3a-139468c5b582" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$134">Aconcagua 3 Jacket (Men's): was $220 now $134</a></strong><br />This lightweight puffer blends recycled down with synthetic insulation for maximum warmth and weather resistance in a tidy, easy-to-stow package. Zonal sheet insulation and a water-repellant finish round out the feature set.<a class="view-deal button" href="https://www.amazon.com/dp/B0CNBVC6HQ?" target="_blank" rel="nofollow" data-dimension112="ac5c8faa-d472-11f1-bf3a-139468c5b582" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$134">View Deal</a></p></div><h3 class="article-body__section" id="section-women-s-jacket-deals"><span>Women's Jacket Deals</span></h3><div class="product"><a data-dimension112="ac5c90a4-d472-11f1-a001-eb1f3bc7b59a" data-action="Deal Block" data-label="Benton Springs Full Zip (Women's)" data-dimension48="Benton Springs Full Zip (Women's)" data-dimension25="$45" href="https://www.amazon.com/Columbia-Womens-Petite-Benton-Springs/dp/B01948PAOE" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2200px;"><p class="vanilla-image-block" style="padding-top:158.45%;"><img id="AJgxuNbZZJZgHs8kBXDwwg" name="Columbia-LBenton-Springs-Full-Zip.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/AJgxuNbZZJZgHs8kBXDwwg-1920-80.jpg" mos="" align="middle" fullscreen="" width="2200" height="3486" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Columbia-Womens-Petite-Benton-Springs/dp/B01948PAOE" target="_blank" rel="nofollow" data-dimension112="ac5c90a4-d472-11f1-a001-eb1f3bc7b59a" data-action="Deal Block" data-label="Benton Springs Full Zip (Women's)" data-dimension48="Benton Springs Full Zip (Women's)" data-dimension25="$45">Benton Springs Full Zip (Women's): was $65 now $45</a></strong><br />Depending on your color and size selection, this soft and cozy full-zip fleece can be yours for as low as $45. The Barton Springs jacket features a 100% polyester fleece construction, two zippered hand-warmer pockets and an adjustable hem. <a class="view-deal button" href="https://www.amazon.com/Columbia-Womens-Petite-Benton-Springs/dp/B01948PAOE" target="_blank" rel="nofollow" data-dimension112="ac5c90a4-d472-11f1-a001-eb1f3bc7b59a" data-action="Deal Block" data-label="Benton Springs Full Zip (Women's)" data-dimension48="Benton Springs Full Zip (Women's)" data-dimension25="$45">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c913a-d472-11f1-9db3-638fc3cd14c9" data-action="Deal Block" data-label="Switchback Jacket (Women's)" data-dimension48="Switchback Jacket (Women's)" data-dimension25="$44" href="https://www.amazon.com/dp/B0CLR14KFG?" 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:164.95%;"><img id="wS5fq4uyAmDFumApbN8rJR" name="Columbia Switchback" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/wS5fq4uyAmDFumApbN8rJR-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1120" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0CLR14KFG?" target="_blank" rel="nofollow" data-dimension112="ac5c913a-d472-11f1-9db3-638fc3cd14c9" data-action="Deal Block" data-label="Switchback Jacket (Women's)" data-dimension48="Switchback Jacket (Women's)" data-dimension25="$44">Switchback Jacket (Women's): was $70 now $44</a></strong><br />This lightweight packable jacket takes up minimal real estate, so there's no excuse not to bring it along on your next outdoor outing. Plus, a hidden hood deploys from the collar when needed and a drawstring hem and adjustable cuffs ensure a watertight fit. <a class="view-deal button" href="https://www.amazon.com/dp/B0CLR14KFG?" target="_blank" rel="nofollow" data-dimension112="ac5c913a-d472-11f1-9db3-638fc3cd14c9" data-action="Deal Block" data-label="Switchback Jacket (Women's)" data-dimension48="Switchback Jacket (Women's)" data-dimension25="$44">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c91bc-d472-11f1-98e9-05c393389d2a" data-action="Deal Block" data-label="Panorama Full Zip (Women's)" data-dimension48="Panorama Full Zip (Women's)" data-dimension25="$47" href="https://www.amazon.com/Columbia-Womens-Panorama-Moonvista-Large/dp/B0CLR9N5PW" 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:202.65%;"><img id="BmSeKyYnTe5vd4ghNKRCf8" name="columbia fleece" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/BmSeKyYnTe5vd4ghNKRCf8-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1376" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Columbia-Womens-Panorama-Moonvista-Large/dp/B0CLR9N5PW" target="_blank" rel="nofollow" data-dimension112="ac5c91bc-d472-11f1-98e9-05c393389d2a" data-action="Deal Block" data-label="Panorama Full Zip (Women's)" data-dimension48="Panorama Full Zip (Women's)" data-dimension25="$47">Panorama Full Zip (Women's): was $100 now $47</a></strong><br />From a light hike to cozying up by the fire, this top-rated Sherpa fleece full zip that's lined with a soft, suede-like material, is perfect for all your outdoor adventures when the air is a bit crisp. It's cut with that classic style and fit you can count on.<a class="view-deal button" href="https://www.amazon.com/Columbia-Womens-Panorama-Moonvista-Large/dp/B0CLR9N5PW" target="_blank" rel="nofollow" data-dimension112="ac5c91bc-d472-11f1-98e9-05c393389d2a" data-action="Deal Block" data-label="Panorama Full Zip (Women's)" data-dimension48="Panorama Full Zip (Women's)" data-dimension25="$47">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c9248-d472-11f1-984d-05497fc41451" data-action="Deal Block" data-label="Rain Defender Packable Anorak (Women's)" data-dimension48="Rain Defender Packable Anorak (Women's)" data-dimension25="$49" href="https://www.amazon.com/dp/B0BNJN3LDM?" 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:221.80%;"><img id="W7hPuJg734Jg83fm9As5Qb" name="Carhartt rain jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/W7hPuJg734Jg83fm9As5Qb-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1506" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0BNJN3LDM?" target="_blank" rel="nofollow" data-dimension112="ac5c9248-d472-11f1-984d-05497fc41451" data-action="Deal Block" data-label="Rain Defender Packable Anorak (Women's)" data-dimension48="Rain Defender Packable Anorak (Women's)" data-dimension25="$49">Rain Defender Packable Anorak (Women's): was $79 now $49</a></strong><br />The Rain Defender Anorak is a lightweight and packable water and wind-resistant half-zip with a large kangaroo-style velcro pocket up front and hidden zippered hand pockets along the side. The two-tone design gives off retro vibes while the roomy, loose-fit cut shouldn't restrict movement. <a class="view-deal button" href="https://www.amazon.com/dp/B0BNJN3LDM?" target="_blank" rel="nofollow" data-dimension112="ac5c9248-d472-11f1-984d-05497fc41451" data-action="Deal Block" data-label="Rain Defender Packable Anorak (Women's)" data-dimension48="Rain Defender Packable Anorak (Women's)" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c92d4-d472-11f1-a196-1f6d913eec39" data-action="Deal Block" data-label="Switchback Jacket II (Women's)" data-dimension48="Switchback Jacket II (Women's)" data-dimension25="$55" href="https://www.amazon.com/Columbia-Womens-Switchback-Jacket-X-Small/dp/B0CLQQMSLN" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:844px;"><p class="vanilla-image-block" style="padding-top:177.73%;"><img id="CyWPJLF7pryTHCeYyQD9xB" name="Switchback Jacket (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/CyWPJLF7pryTHCeYyQD9xB-1920-80.jpg" mos="" align="middle" fullscreen="" width="844" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Columbia-Womens-Switchback-Jacket-X-Small/dp/B0CLQQMSLN" target="_blank" rel="nofollow" data-dimension112="ac5c92d4-d472-11f1-a196-1f6d913eec39" data-action="Deal Block" data-label="Switchback Jacket II (Women's)" data-dimension48="Switchback Jacket II (Women's)" data-dimension25="$55">Switchback Jacket II (Women's): was $100 now $55</a></strong><br />Right now you can get this Columbia rain jacket with up to 44% off, which is a steal. It protects against light precipitation, so it's a great companion for fall. It also dries fast when it does get wet.<a class="view-deal button" href="https://www.amazon.com/Columbia-Womens-Switchback-Jacket-X-Small/dp/B0CLQQMSLN" target="_blank" rel="nofollow" data-dimension112="ac5c92d4-d472-11f1-a196-1f6d913eec39" data-action="Deal Block" data-label="Switchback Jacket II (Women's)" data-dimension48="Switchback Jacket II (Women's)" data-dimension25="$55">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c936a-d472-11f1-af9f-75764f47687a" data-action="Deal Block" data-label="Monterey Jacket (Women's)" data-dimension48="Monterey Jacket (Women's)" data-dimension25="$55" href="https://www.amazon.com/Carhartt-Womens-Defender-Lightweight-Packable/dp/B0F96WVJNC?" 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:201.18%;"><img id="WrHCmC5ZrvbsGGNpQnXLYL" name="Monterrey Jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/WrHCmC5ZrvbsGGNpQnXLYL-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1366" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Carhartt-Womens-Defender-Lightweight-Packable/dp/B0F96WVJNC?" target="_blank" rel="nofollow" data-dimension112="ac5c936a-d472-11f1-af9f-75764f47687a" data-action="Deal Block" data-label="Monterey Jacket (Women's)" data-dimension48="Monterey Jacket (Women's)" data-dimension25="$55">Monterey Jacket (Women's): was $99 now $55</a></strong><br />Don't get caught in a rainstorm without this jacket. It features waterproof, breathable technology that stops water from getting in but lets sweat get out. It also has Wind Fighter technology to combat the elements. <a class="view-deal button" href="https://www.amazon.com/Carhartt-Womens-Defender-Lightweight-Packable/dp/B0F96WVJNC?" target="_blank" rel="nofollow" data-dimension112="ac5c936a-d472-11f1-af9f-75764f47687a" data-action="Deal Block" data-label="Monterey Jacket (Women's)" data-dimension48="Monterey Jacket (Women's)" data-dimension25="$55">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c9428-d472-11f1-a16a-91d15f768d7f" data-action="Deal Block" data-label="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension48="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension25="$74" href="https://www.rei.com/product/C00697/the-north-face-yumiori-off-peak-full-zip-jacket-womens" 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="vamU4Ky2CB4QQda8nfrvm4" name="the north face yumiori jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vamU4Ky2CB4QQda8nfrvm4-1920-80.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C00697/the-north-face-yumiori-off-peak-full-zip-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ac5c9428-d472-11f1-a16a-91d15f768d7f" data-action="Deal Block" data-label="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension48="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension25="$74">Yumiori Off Peak Full-Zip Jacket - Women's: was $150 now $74</a></strong><br />The North Face's Yumiori fleece is a perfect hiking-slash-everyday fleece. Smartphones fit snugly into the chest pocket, one zipper even doubles as a hair tie, and it's finished with durable water repellent.<a class="view-deal button" href="https://www.rei.com/product/C00697/the-north-face-yumiori-off-peak-full-zip-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ac5c9428-d472-11f1-a16a-91d15f768d7f" data-action="Deal Block" data-label="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension48="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension25="$74">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c9496-d472-11f1-921d-055d5d5c368c" data-action="Deal Block" data-label="Antora Jacket (Women's)" data-dimension48="Antora Jacket (Women's)" data-dimension25="$91" href="https://www.amazon.com/dp/B0F97WG8SQ?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:731px;"><p class="vanilla-image-block" style="padding-top:205.20%;"><img id="bN5BuTC38YdrnSkcwmxwpg" name="Antora Jacket (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bN5BuTC38YdrnSkcwmxwpg-1920-80.jpg" mos="" align="middle" fullscreen="" width="731" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0F97WG8SQ?" target="_blank" rel="nofollow" data-dimension112="ac5c9496-d472-11f1-921d-055d5d5c368c" data-action="Deal Block" data-label="Antora Jacket (Women's)" data-dimension48="Antora Jacket (Women's)" data-dimension25="$91">Antora Jacket (Women's): was $130 now $91</a></strong><br />$91 is a great deal for this lightweight, weather-resistant shell. A core piece of outerwear no one should leave home without, the Antora Jacket boasts impressive rain-repellent capabilities. A drawstring-adjustable hood provides extra H2O protection, while a storm flap protects the main zipper from seepage during downpours. More importantly, as far as rain shells go, few can match the style factor of the Antora. <a class="view-deal button" href="https://www.amazon.com/dp/B0F97WG8SQ?" target="_blank" rel="nofollow" data-dimension112="ac5c9496-d472-11f1-921d-055d5d5c368c" data-action="Deal Block" data-label="Antora Jacket (Women's)" data-dimension48="Antora Jacket (Women's)" data-dimension25="$91">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c950e-d472-11f1-af0b-411f148a634c" data-action="Deal Block" data-label="R1 Pullover (Women's)" data-dimension48="R1 Pullover (Women's)" data-dimension25="$107" href="https://www.rei.com/product/242323/patagonia-r1-pullover-womens" 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="bre5ZuSFLvwfm5qxrkvwTm" name="patagonia r1 pullover" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bre5ZuSFLvwfm5qxrkvwTm-1920-80.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/242323/patagonia-r1-pullover-womens" target="_blank" rel="nofollow" data-dimension112="ac5c950e-d472-11f1-af0b-411f148a634c" data-action="Deal Block" data-label="R1 Pullover (Women's)" data-dimension48="R1 Pullover (Women's)" data-dimension25="$107">R1 Pullover (Women's): was $155 now $107</a></strong><br />The Patagonia R1 Pullover is a midlayer, meaning it's intended to be worn between a thermal base layer and an outer waterproof or windproof jacket like the Patagonia Houdini. <a class="view-deal button" href="https://www.rei.com/product/242323/patagonia-r1-pullover-womens" target="_blank" rel="nofollow" data-dimension112="ac5c950e-d472-11f1-af0b-411f148a634c" data-action="Deal Block" data-label="R1 Pullover (Women's)" data-dimension48="R1 Pullover (Women's)" data-dimension25="$107">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c9586-d472-11f1-a255-9f68d50876bf" data-action="Deal Block" data-label="Arctic Parka (Women's)" data-dimension48="Arctic Parka (Women's)" data-dimension25="$350" href="https://www.amazon.com/North-Face-Womens-Arctic-Parka/dp/B0DSQ5M945" 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:192.34%;"><img id="JnwKQnbwffvW93sFWc4647" name="Arctic Parka (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/JnwKQnbwffvW93sFWc4647-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1306" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/North-Face-Womens-Arctic-Parka/dp/B0DSQ5M945" target="_blank" rel="nofollow" data-dimension112="ac5c9586-d472-11f1-a255-9f68d50876bf" data-action="Deal Block" data-label="Arctic Parka (Women's)" data-dimension48="Arctic Parka (Women's)" data-dimension25="$350">Arctic Parka (Women's): was $400 now $350</a></strong><br />When only the warmest coat will do, grab this Arctic Parka from The North Face. It's packed with 600-fill waterfowl down insulation, but is lightweight and packs away easily when the weather changes.<a class="view-deal button" href="https://www.amazon.com/North-Face-Womens-Arctic-Parka/dp/B0DSQ5M945" target="_blank" rel="nofollow" data-dimension112="ac5c9586-d472-11f1-a255-9f68d50876bf" data-action="Deal Block" data-label="Arctic Parka (Women's)" data-dimension48="Arctic Parka (Women's)" data-dimension25="$350">View Deal</a></p></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness/21-best-fall-jacket-and-fleece-deals-to-shop-before-black-friday-up-to-50-percent-off-the-north-face-patagonia-and-more</link>
                                                                            <description>
                            <![CDATA[ I'm sharing my favorite jackets from Patagonia, The North Face and Carhartt to make sure you're comfortable and dry this fall — all on sale ahead of Black Friday ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">3BcwC4McvU75vsMGLhv8gY</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/EBNi5gMAq9qNuUfC3tLa7Q-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 30 Oct 2026 15:32:39 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Fitness]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Olivia Halevy ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/YAg7Fmh9dGKbg3hULBMWiU-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Olivia is a Deals Writer at Tom’s Guide. She loves all things lifestyle, shopping and sourcing the best deals from some of the top brands, retailers and websites around. From fashion and beauty to smart home and tech, she has an eye for finding practical, stylish, and reasonably-priced items that help make life simpler (and a little more aesthetically-pleasing).&amp;nbsp;Olivia has over five years of experience writing lifestyle, commerce, and branded content for &lt;a href=&quot;http://patch.com/&quot;&gt;Patch.com&lt;/a&gt;. She&#039;s covered major shopping holidays like Amazon Prime Day, Black Friday and Cyber Monday. In her free time, she enjoys trying out new exercise classes, binge-watching the latest viral TV shows, cooking, spending time with family and taking long walks with her dog, Gus.&amp;nbsp;&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/EBNi5gMAq9qNuUfC3tLa7Q-1920-80.jpg">
                                                            <media:credit><![CDATA[REI / edited by Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[REI sale]]></media:description>                                                            <media:text><![CDATA[REI sale]]></media:text>
                                <media:title type="plain"><![CDATA[REI sale]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/EBNi5gMAq9qNuUfC3tLa7Q-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>With temperatures dropping and inclement weather just around the corner, now’s the perfect time to give your jacket and fleece lineup an upgrade. And luckily, you've come to the right place — we're already spotting tons of deals ahead of Black Friday, which means you can bundle up for less. </p><p>Retailers like Amazon and REI are slashing the prices on best-selling styles from Patagonia, The North Face, Carhartt and more. From affordable options under $50 to premium picks that are worth the splurge, there’s something for every budget. </p><p>If you're ready to grab some new layers for fall, keep scrolling to check out my favorite jacket and fleece deals to shop before Black Friday rolls around. </p><p><strong>Note: </strong>Prices may vary depending on the size and color you select (particularly on Amazon). Check out any different color options available in your size to find the best deals.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><strong></strong><a href="https://www.amazon.com/deals/?" target="_blank" rel="nofollow"><strong>shop all Amazon deals</strong></a></li><li><strong></strong><a href="https://www.rei.com/f/scd-deals" target="_blank" rel="nofollow"><strong>shop all REI deals</strong></a></li><li><strong>Columbia Glennaker Lake II Rain Jacket (Men's): </strong><a href="https://www.amazon.com/Columbia-Glennaker-Jacket-Black-Large/dp/B0CLR8QXKW" target="_blank" rel="nofollow"><strong>was $70 now $42</strong></a></li><li><strong>Carhartt Force Relaxed Fit Full-Zip Long-Sleeve (Men's): </strong><a href="https://www.amazon.com/dp/B0DMTFDTC7?" target="_blank" rel="nofollow"><strong>was $84 now $44</strong></a></li><li><strong>Columbia Switchback Jacket (Women's): </strong><a href="https://www.amazon.com/dp/B0CLR14KFG?" target="_blank" rel="nofollow"><strong>was $70 now $44</strong></a></li><li><strong>Carhartt Rain Defender Packable Anorak (Women's): </strong><a href="https://www.amazon.com/Carhartt-Defender-Lightweight-Packable-Asphalt/dp/B0DK5SZKCN?" target="_blank" rel="nofollow"><strong>was $79 now $49</strong></a></li><li><strong>The North Face Antora Jacket (Women's): </strong><a href="https://www.amazon.com/North-Face-Waterproof-Windproof-Adjustable/dp/B0F97WG8SQ?" target="_blank" rel="nofollow"><strong>was $130 now $91</strong></a></li><li><strong>Patagonia Houdini Half-Zip (Men's): </strong><a href="https://www.rei.com/product/228564/patagonia-houdini-stash-half-zip-jacket-mens?color=CASCADE%2520GREEN" target="_blank" rel="nofollow"><strong>was $139 now $100</strong></a></li><li><strong>Arc'teryx Squamish Hoody (Men's): </strong><a href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow"><strong>was $200 now $119</strong></a></li><li><strong>The North Face Aconcagua 3 Jacket (Men's): </strong><a href="https://www.amazon.com/dp/B0CNBVC6HQ?" target="_blank" rel="nofollow"><strong>was $220 now $134</strong></a></li></ul><h3 class="article-body__section" id="section-men-s-jacket-deals"><span>Men's Jacket Deals</span></h3><div class="product"><a data-dimension112="ac5c8938-d472-11f1-855d-39a681cafec4" data-action="Deal Block" data-label="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension48="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension25="$44" href="https://www.amazon.com/dp/B0DMTFDTC7?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:594px;"><p class="vanilla-image-block" style="padding-top:168.18%;"><img id="XVAtjBrciTnPeT2AD3fLvm" name="Long Sleeve Full zip" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XVAtjBrciTnPeT2AD3fLvm-1920-80.jpg" mos="" align="middle" fullscreen="" width="594" height="999" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0DMTFDTC7?" target="_blank" rel="nofollow" data-dimension112="ac5c8938-d472-11f1-855d-39a681cafec4" data-action="Deal Block" data-label="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension48="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension25="$44">Force Relaxed Fit Full-Zip Long-Sleeve (Men's): was $84 now $44</a></strong><br />Perfect for a casual stroll, low-intensity workout or a longer run, this versatile layer features Carhartt Force technology to wick sweat, dry fast, and fight odors. It's a full zip and allows for a full range of motion too. <a class="view-deal button" href="https://www.amazon.com/dp/B0DMTFDTC7?" target="_blank" rel="nofollow" data-dimension112="ac5c8938-d472-11f1-855d-39a681cafec4" data-action="Deal Block" data-label="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension48="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension25="$44">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c89b0-d472-11f1-8c92-1dfc0007624b" data-action="Deal Block" data-label="Glennaker Lake II Rain Jacket (Men's)" data-dimension48="Glennaker Lake II Rain Jacket (Men's)" data-dimension25="$42" href="https://www.amazon.com/Columbia-Glennaker-Jacket-Black-Large/dp/B0CLR8QXKW" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1105px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="Gp4VGe8Q8YaFDrascG72q" name="Columbia-m-glennaker" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Gp4VGe8Q8YaFDrascG72q-1920-80.jpg" mos="" align="middle" fullscreen="" width="1105" height="1105" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Columbia-Glennaker-Jacket-Black-Large/dp/B0CLR8QXKW" target="_blank" rel="nofollow" data-dimension112="ac5c89b0-d472-11f1-8c92-1dfc0007624b" data-action="Deal Block" data-label="Glennaker Lake II Rain Jacket (Men's)" data-dimension48="Glennaker Lake II Rain Jacket (Men's)" data-dimension25="$42">Glennaker Lake II Rain Jacket (Men's): was $70 now $42</a></strong><br />Need an affordable just-in-case rain jacket? Look no further than the Columbia Glennaker Lake. Made from 100% nylon, it features a stow-away hood that folds into the collar, zippered hand pockets, elastic cuffs and an adjustable hem. It's also small and light enough to shove inside a backpack or purse.<a class="view-deal button" href="https://www.amazon.com/Columbia-Glennaker-Jacket-Black-Large/dp/B0CLR8QXKW" target="_blank" rel="nofollow" data-dimension112="ac5c89b0-d472-11f1-8c92-1dfc0007624b" data-action="Deal Block" data-label="Glennaker Lake II Rain Jacket (Men's)" data-dimension48="Glennaker Lake II Rain Jacket (Men's)" data-dimension25="$42">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c8a28-d472-11f1-b575-f7676b82071a" data-action="Deal Block" data-label="Steens Mountain Full Zip 2.0 (Men's)" data-dimension48="Steens Mountain Full Zip 2.0 (Men's)" data-dimension25="$34" href="https://www.amazon.com/dp/B0FYJJTZJY?" 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:155.96%;"><img id="Bv68Qo72tT3oKtVBP7Czii" name="Columbia Fleece.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Bv68Qo72tT3oKtVBP7Czii-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1059" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0FYJJTZJY?" target="_blank" rel="nofollow" data-dimension112="ac5c8a28-d472-11f1-b575-f7676b82071a" data-action="Deal Block" data-label="Steens Mountain Full Zip 2.0 (Men's)" data-dimension48="Steens Mountain Full Zip 2.0 (Men's)" data-dimension25="$34">Steens Mountain Full Zip 2.0 (Men's): was $65 now $34</a></strong><br />The perfect grab and go zip up, this jacket is made of soft polyester fleece fabric and will keep you warm as the temperatures drop. Available in several different colors, it will definitely be an outdoor staple this fall. <a class="view-deal button" href="https://www.amazon.com/dp/B0FYJJTZJY?" target="_blank" rel="nofollow" data-dimension112="ac5c8a28-d472-11f1-b575-f7676b82071a" data-action="Deal Block" data-label="Steens Mountain Full Zip 2.0 (Men's)" data-dimension48="Steens Mountain Full Zip 2.0 (Men's)" data-dimension25="$34">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c8aa0-d472-11f1-80ce-a71a8d70af53" data-action="Deal Block" data-label="Ascender Softshell Rain Jacket (Men's)" data-dimension48="Ascender Softshell Rain Jacket (Men's)" data-dimension25="$49" href="https://www.amazon.com/dp/B0CLRBK7P2?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:829px;"><p class="vanilla-image-block" style="padding-top:100.12%;"><img id="RxbCzBdr6qyZyeYxwMo4jE" name="Columbia-m-ascender" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/RxbCzBdr6qyZyeYxwMo4jE-1920-80.jpg" mos="" align="middle" fullscreen="" width="829" height="830" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0CLRBK7P2?" target="_blank" rel="nofollow" data-dimension112="ac5c8aa0-d472-11f1-80ce-a71a8d70af53" data-action="Deal Block" data-label="Ascender Softshell Rain Jacket (Men's)" data-dimension48="Ascender Softshell Rain Jacket (Men's)" data-dimension25="$49">Ascender Softshell Rain Jacket (Men's): was $125 now $49</a></strong><br />This stretchy, chic softshell isn't for torrential downpours but will keep you dry in light rain and drizzle. Made from 100% polyester, it features zippered hand and chest pockets, an abrasion-resistant chin guard and an adjustable hem and cuffs. <a class="view-deal button" href="https://www.amazon.com/dp/B0CLRBK7P2?" target="_blank" rel="nofollow" data-dimension112="ac5c8aa0-d472-11f1-80ce-a71a8d70af53" data-action="Deal Block" data-label="Ascender Softshell Rain Jacket (Men's)" data-dimension48="Ascender Softshell Rain Jacket (Men's)" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c8b18-d472-11f1-bb3f-a9ba4ca78788" data-action="Deal Block" data-label="Rain Defender Jacket (Men's)" data-dimension48="Rain Defender Jacket (Men's)" data-dimension25="$74" href="https://www.amazon.com/Carhartt-Defender-Relaxed-Jacket-Ocean/dp/B0F8PLPT7B?" 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:127.84%;"><img id="VVpm8JrkWovdG4VCm3q4We" name="Rain Defender Jacket (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/VVpm8JrkWovdG4VCm3q4We-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="868" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Carhartt-Defender-Relaxed-Jacket-Ocean/dp/B0F8PLPT7B?" target="_blank" rel="nofollow" data-dimension112="ac5c8b18-d472-11f1-bb3f-a9ba4ca78788" data-action="Deal Block" data-label="Rain Defender Jacket (Men's)" data-dimension48="Rain Defender Jacket (Men's)" data-dimension25="$74">Rain Defender Jacket (Men's): was $99 now $74</a></strong><br />The Carhartt Rain Defender Jacket is now on sale from $74. It's perfect to take on wind and rain, while keeping you warm and dry. It's durable and moves with you thanks to its Rugged Flex stretch technology.<a class="view-deal button" href="https://www.amazon.com/Carhartt-Defender-Relaxed-Jacket-Ocean/dp/B0F8PLPT7B?" target="_blank" rel="nofollow" data-dimension112="ac5c8b18-d472-11f1-bb3f-a9ba4ca78788" data-action="Deal Block" data-label="Rain Defender Jacket (Men's)" data-dimension48="Rain Defender Jacket (Men's)" data-dimension25="$74">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c8b90-d472-11f1-b2aa-c1c978bc623a" data-action="Deal Block" data-label="Fleece Pullover (Men's)" data-dimension48="Fleece Pullover (Men's)" data-dimension25="$79" href="https://www.amazon.com/Carhartt-Loose-Fleece-Pullover-Oatmeal/dp/B0CR1X544H" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:658px;"><p class="vanilla-image-block" style="padding-top:151.82%;"><img id="cmnpDDU8xQkc4aDsdWRj3d" name="Carhartt fleece" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/cmnpDDU8xQkc4aDsdWRj3d-1920-80.jpg" mos="" align="middle" fullscreen="" width="658" height="999" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Carhartt-Loose-Fleece-Pullover-Oatmeal/dp/B0CR1X544H" target="_blank" rel="nofollow" data-dimension112="ac5c8b90-d472-11f1-b2aa-c1c978bc623a" data-action="Deal Block" data-label="Fleece Pullover (Men's)" data-dimension48="Fleece Pullover (Men's)" data-dimension25="$79">Fleece Pullover (Men's): was $99 now $79</a></strong><br />If you're looking for a pullover that feels like a warm hug, this is the one! The cozy quarter zip is the perfect layer for fall and features a loose fit for extra comfort. <a class="view-deal button" href="https://www.amazon.com/Carhartt-Loose-Fleece-Pullover-Oatmeal/dp/B0CR1X544H" target="_blank" rel="nofollow" data-dimension112="ac5c8b90-d472-11f1-b2aa-c1c978bc623a" data-action="Deal Block" data-label="Fleece Pullover (Men's)" data-dimension48="Fleece Pullover (Men's)" data-dimension25="$79">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c8c08-d472-11f1-84ef-17d33ce6716f" data-action="Deal Block" data-label="Powder Lite II Jacket (Men's)" data-dimension48="Powder Lite II Jacket (Men's)" data-dimension25="$99" href="https://www.amazon.com/Columbia-Powder-Jacket-Black-Large/dp/B0CLRBRZHS" 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:189.84%;"><img id="BtaCy7tDVwYLGzNAQeJusG" name="Powder Lite II Jacket (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/BtaCy7tDVwYLGzNAQeJusG-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1289" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Columbia-Powder-Jacket-Black-Large/dp/B0CLRBRZHS" target="_blank" rel="nofollow" data-dimension112="ac5c8c08-d472-11f1-84ef-17d33ce6716f" data-action="Deal Block" data-label="Powder Lite II Jacket (Men's)" data-dimension48="Powder Lite II Jacket (Men's)" data-dimension25="$99">Powder Lite II Jacket (Men's): was $165 now $99</a></strong><br />Columbia’s Omni-Heat thermal-reflective lining retains your body's own warmth, and the puffer also has a water-resistant outer layer for wet weather. Plus, it stows easily and is super lightweight if you enjoy hiking.<a class="view-deal button" href="https://www.amazon.com/Columbia-Powder-Jacket-Black-Large/dp/B0CLRBRZHS" target="_blank" rel="nofollow" data-dimension112="ac5c8c08-d472-11f1-84ef-17d33ce6716f" data-action="Deal Block" data-label="Powder Lite II Jacket (Men's)" data-dimension48="Powder Lite II Jacket (Men's)" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c8c80-d472-11f1-b21a-139d9f5a7dfb" data-action="Deal Block" data-label="Houdini Half-Zip (Men's)" data-dimension48="Houdini Half-Zip (Men's)" data-dimension25="$100" href="https://www.rei.com/product/228564/patagonia-houdini-stash-half-zip-jacket-mens?color=CASCADE%2520GREEN" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1090px;"><p class="vanilla-image-block" style="padding-top:112.75%;"><img id="Ae9C3N28VXVi824kshL69a" name="Screenshot 2026-06-15 at 9.10.35 PM" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Ae9C3N28VXVi824kshL69a-1920-80.png" mos="" align="middle" fullscreen="" width="1090" height="1229" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/228564/patagonia-houdini-stash-half-zip-jacket-mens?color=CASCADE%2520GREEN" target="_blank" rel="nofollow" data-dimension112="ac5c8c80-d472-11f1-b21a-139d9f5a7dfb" data-action="Deal Block" data-label="Houdini Half-Zip (Men's)" data-dimension48="Houdini Half-Zip (Men's)" data-dimension25="$100">Houdini Half-Zip (Men's): was $139 now $100</a></strong><br />The Patagonia Houdini Half-Zip is nothing short of pure magic. This back-pocket-packable pull-over weighs about as much as a deck of playing cards, yet offers seriously solid protection from the rain, wind and chill.<a class="view-deal button" href="https://www.rei.com/product/228564/patagonia-houdini-stash-half-zip-jacket-mens?color=CASCADE%2520GREEN" target="_blank" rel="nofollow" data-dimension112="ac5c8c80-d472-11f1-b21a-139d9f5a7dfb" data-action="Deal Block" data-label="Houdini Half-Zip (Men's)" data-dimension48="Houdini Half-Zip (Men's)" data-dimension25="$100">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c8e1a-d472-11f1-8706-914af691c77a" data-action="Deal Block" data-label="Squamish Hoody (Men's)" data-dimension48="Squamish Hoody (Men's)" data-dimension25="$119" href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="gU2HZNV4QV8x48bVFDMoVL" name="Arc'teryx Squamish" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gU2HZNV4QV8x48bVFDMoVL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow" data-dimension112="ac5c8e1a-d472-11f1-8706-914af691c77a" data-action="Deal Block" data-label="Squamish Hoody (Men's)" data-dimension48="Squamish Hoody (Men's)" data-dimension25="$119">Squamish Hoody (Men's): was $200 now $119</a></strong><br />The Arc'teryx Squamish Hoody is completely windproof and finished with DWR, making it a versatile outer layer for those nippy wintry hikes. There's even a capped hood for keeping your face dry. There are currently six colors discounted at varying price points. <a class="view-deal button" href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow" data-dimension112="ac5c8e1a-d472-11f1-8706-914af691c77a" data-action="Deal Block" data-label="Squamish Hoody (Men's)" data-dimension48="Squamish Hoody (Men's)" data-dimension25="$119">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c8eba-d472-11f1-bbb5-9bf2db6ffbb3" data-action="Deal Block" data-label="Daily Snap-T Pullover (Men's)" data-dimension48="Daily Snap-T Pullover (Men's)" data-dimension25="$124" href="https://www.rei.com/product/C01345/patagonia-daily-snap-t-pullover-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1560px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="WGXNCXSCXiBba8uzoeFYnS" name="Patagonia Snap T" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/WGXNCXSCXiBba8uzoeFYnS-1920-80.jpg" mos="" align="middle" fullscreen="" width="1560" height="1560" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01345/patagonia-daily-snap-t-pullover-mens" target="_blank" rel="nofollow" data-dimension112="ac5c8eba-d472-11f1-bbb5-9bf2db6ffbb3" data-action="Deal Block" data-label="Daily Snap-T Pullover (Men's)" data-dimension48="Daily Snap-T Pullover (Men's)" data-dimension25="$124">Daily Snap-T Pullover (Men's): was $179 now $124</a></strong><br />This is the same as the deal listed above, except it's the men's version. It's available in nearly every single size in three different colors, so you'll be able to find your perfect fit. <a class="view-deal button" href="https://www.rei.com/product/C01345/patagonia-daily-snap-t-pullover-mens" target="_blank" rel="nofollow" data-dimension112="ac5c8eba-d472-11f1-bbb5-9bf2db6ffbb3" data-action="Deal Block" data-label="Daily Snap-T Pullover (Men's)" data-dimension48="Daily Snap-T Pullover (Men's)" data-dimension25="$124">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c8faa-d472-11f1-bf3a-139468c5b582" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$134" href="https://www.amazon.com/dp/B0CNBVC6HQ?" 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:187.78%;"><img id="jLN4YbW223nKsxQxPVPWZR" name="TNF jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jLN4YbW223nKsxQxPVPWZR-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1275" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0CNBVC6HQ?" target="_blank" rel="nofollow" data-dimension112="ac5c8faa-d472-11f1-bf3a-139468c5b582" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$134">Aconcagua 3 Jacket (Men's): was $220 now $134</a></strong><br />This lightweight puffer blends recycled down with synthetic insulation for maximum warmth and weather resistance in a tidy, easy-to-stow package. Zonal sheet insulation and a water-repellant finish round out the feature set.<a class="view-deal button" href="https://www.amazon.com/dp/B0CNBVC6HQ?" target="_blank" rel="nofollow" data-dimension112="ac5c8faa-d472-11f1-bf3a-139468c5b582" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$134">View Deal</a></p></div><h3 class="article-body__section" id="section-women-s-jacket-deals"><span>Women's Jacket Deals</span></h3><div class="product"><a data-dimension112="ac5c90a4-d472-11f1-a001-eb1f3bc7b59a" data-action="Deal Block" data-label="Benton Springs Full Zip (Women's)" data-dimension48="Benton Springs Full Zip (Women's)" data-dimension25="$45" href="https://www.amazon.com/Columbia-Womens-Petite-Benton-Springs/dp/B01948PAOE" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2200px;"><p class="vanilla-image-block" style="padding-top:158.45%;"><img id="AJgxuNbZZJZgHs8kBXDwwg" name="Columbia-LBenton-Springs-Full-Zip.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/AJgxuNbZZJZgHs8kBXDwwg-1920-80.jpg" mos="" align="middle" fullscreen="" width="2200" height="3486" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Columbia-Womens-Petite-Benton-Springs/dp/B01948PAOE" target="_blank" rel="nofollow" data-dimension112="ac5c90a4-d472-11f1-a001-eb1f3bc7b59a" data-action="Deal Block" data-label="Benton Springs Full Zip (Women's)" data-dimension48="Benton Springs Full Zip (Women's)" data-dimension25="$45">Benton Springs Full Zip (Women's): was $65 now $45</a></strong><br />Depending on your color and size selection, this soft and cozy full-zip fleece can be yours for as low as $45. The Barton Springs jacket features a 100% polyester fleece construction, two zippered hand-warmer pockets and an adjustable hem. <a class="view-deal button" href="https://www.amazon.com/Columbia-Womens-Petite-Benton-Springs/dp/B01948PAOE" target="_blank" rel="nofollow" data-dimension112="ac5c90a4-d472-11f1-a001-eb1f3bc7b59a" data-action="Deal Block" data-label="Benton Springs Full Zip (Women's)" data-dimension48="Benton Springs Full Zip (Women's)" data-dimension25="$45">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c913a-d472-11f1-9db3-638fc3cd14c9" data-action="Deal Block" data-label="Switchback Jacket (Women's)" data-dimension48="Switchback Jacket (Women's)" data-dimension25="$44" href="https://www.amazon.com/dp/B0CLR14KFG?" 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:164.95%;"><img id="wS5fq4uyAmDFumApbN8rJR" name="Columbia Switchback" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/wS5fq4uyAmDFumApbN8rJR-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1120" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0CLR14KFG?" target="_blank" rel="nofollow" data-dimension112="ac5c913a-d472-11f1-9db3-638fc3cd14c9" data-action="Deal Block" data-label="Switchback Jacket (Women's)" data-dimension48="Switchback Jacket (Women's)" data-dimension25="$44">Switchback Jacket (Women's): was $70 now $44</a></strong><br />This lightweight packable jacket takes up minimal real estate, so there's no excuse not to bring it along on your next outdoor outing. Plus, a hidden hood deploys from the collar when needed and a drawstring hem and adjustable cuffs ensure a watertight fit. <a class="view-deal button" href="https://www.amazon.com/dp/B0CLR14KFG?" target="_blank" rel="nofollow" data-dimension112="ac5c913a-d472-11f1-9db3-638fc3cd14c9" data-action="Deal Block" data-label="Switchback Jacket (Women's)" data-dimension48="Switchback Jacket (Women's)" data-dimension25="$44">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c91bc-d472-11f1-98e9-05c393389d2a" data-action="Deal Block" data-label="Panorama Full Zip (Women's)" data-dimension48="Panorama Full Zip (Women's)" data-dimension25="$47" href="https://www.amazon.com/Columbia-Womens-Panorama-Moonvista-Large/dp/B0CLR9N5PW" 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:202.65%;"><img id="BmSeKyYnTe5vd4ghNKRCf8" name="columbia fleece" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/BmSeKyYnTe5vd4ghNKRCf8-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1376" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Columbia-Womens-Panorama-Moonvista-Large/dp/B0CLR9N5PW" target="_blank" rel="nofollow" data-dimension112="ac5c91bc-d472-11f1-98e9-05c393389d2a" data-action="Deal Block" data-label="Panorama Full Zip (Women's)" data-dimension48="Panorama Full Zip (Women's)" data-dimension25="$47">Panorama Full Zip (Women's): was $100 now $47</a></strong><br />From a light hike to cozying up by the fire, this top-rated Sherpa fleece full zip that's lined with a soft, suede-like material, is perfect for all your outdoor adventures when the air is a bit crisp. It's cut with that classic style and fit you can count on.<a class="view-deal button" href="https://www.amazon.com/Columbia-Womens-Panorama-Moonvista-Large/dp/B0CLR9N5PW" target="_blank" rel="nofollow" data-dimension112="ac5c91bc-d472-11f1-98e9-05c393389d2a" data-action="Deal Block" data-label="Panorama Full Zip (Women's)" data-dimension48="Panorama Full Zip (Women's)" data-dimension25="$47">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c9248-d472-11f1-984d-05497fc41451" data-action="Deal Block" data-label="Rain Defender Packable Anorak (Women's)" data-dimension48="Rain Defender Packable Anorak (Women's)" data-dimension25="$49" href="https://www.amazon.com/dp/B0BNJN3LDM?" 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:221.80%;"><img id="W7hPuJg734Jg83fm9As5Qb" name="Carhartt rain jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/W7hPuJg734Jg83fm9As5Qb-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1506" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0BNJN3LDM?" target="_blank" rel="nofollow" data-dimension112="ac5c9248-d472-11f1-984d-05497fc41451" data-action="Deal Block" data-label="Rain Defender Packable Anorak (Women's)" data-dimension48="Rain Defender Packable Anorak (Women's)" data-dimension25="$49">Rain Defender Packable Anorak (Women's): was $79 now $49</a></strong><br />The Rain Defender Anorak is a lightweight and packable water and wind-resistant half-zip with a large kangaroo-style velcro pocket up front and hidden zippered hand pockets along the side. The two-tone design gives off retro vibes while the roomy, loose-fit cut shouldn't restrict movement. <a class="view-deal button" href="https://www.amazon.com/dp/B0BNJN3LDM?" target="_blank" rel="nofollow" data-dimension112="ac5c9248-d472-11f1-984d-05497fc41451" data-action="Deal Block" data-label="Rain Defender Packable Anorak (Women's)" data-dimension48="Rain Defender Packable Anorak (Women's)" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c92d4-d472-11f1-a196-1f6d913eec39" data-action="Deal Block" data-label="Switchback Jacket II (Women's)" data-dimension48="Switchback Jacket II (Women's)" data-dimension25="$55" href="https://www.amazon.com/Columbia-Womens-Switchback-Jacket-X-Small/dp/B0CLQQMSLN" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:844px;"><p class="vanilla-image-block" style="padding-top:177.73%;"><img id="CyWPJLF7pryTHCeYyQD9xB" name="Switchback Jacket (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/CyWPJLF7pryTHCeYyQD9xB-1920-80.jpg" mos="" align="middle" fullscreen="" width="844" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Columbia-Womens-Switchback-Jacket-X-Small/dp/B0CLQQMSLN" target="_blank" rel="nofollow" data-dimension112="ac5c92d4-d472-11f1-a196-1f6d913eec39" data-action="Deal Block" data-label="Switchback Jacket II (Women's)" data-dimension48="Switchback Jacket II (Women's)" data-dimension25="$55">Switchback Jacket II (Women's): was $100 now $55</a></strong><br />Right now you can get this Columbia rain jacket with up to 44% off, which is a steal. It protects against light precipitation, so it's a great companion for fall. It also dries fast when it does get wet.<a class="view-deal button" href="https://www.amazon.com/Columbia-Womens-Switchback-Jacket-X-Small/dp/B0CLQQMSLN" target="_blank" rel="nofollow" data-dimension112="ac5c92d4-d472-11f1-a196-1f6d913eec39" data-action="Deal Block" data-label="Switchback Jacket II (Women's)" data-dimension48="Switchback Jacket II (Women's)" data-dimension25="$55">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c936a-d472-11f1-af9f-75764f47687a" data-action="Deal Block" data-label="Monterey Jacket (Women's)" data-dimension48="Monterey Jacket (Women's)" data-dimension25="$55" href="https://www.amazon.com/Carhartt-Womens-Defender-Lightweight-Packable/dp/B0F96WVJNC?" 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:201.18%;"><img id="WrHCmC5ZrvbsGGNpQnXLYL" name="Monterrey Jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/WrHCmC5ZrvbsGGNpQnXLYL-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1366" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Carhartt-Womens-Defender-Lightweight-Packable/dp/B0F96WVJNC?" target="_blank" rel="nofollow" data-dimension112="ac5c936a-d472-11f1-af9f-75764f47687a" data-action="Deal Block" data-label="Monterey Jacket (Women's)" data-dimension48="Monterey Jacket (Women's)" data-dimension25="$55">Monterey Jacket (Women's): was $99 now $55</a></strong><br />Don't get caught in a rainstorm without this jacket. It features waterproof, breathable technology that stops water from getting in but lets sweat get out. It also has Wind Fighter technology to combat the elements. <a class="view-deal button" href="https://www.amazon.com/Carhartt-Womens-Defender-Lightweight-Packable/dp/B0F96WVJNC?" target="_blank" rel="nofollow" data-dimension112="ac5c936a-d472-11f1-af9f-75764f47687a" data-action="Deal Block" data-label="Monterey Jacket (Women's)" data-dimension48="Monterey Jacket (Women's)" data-dimension25="$55">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c9428-d472-11f1-a16a-91d15f768d7f" data-action="Deal Block" data-label="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension48="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension25="$74" href="https://www.rei.com/product/C00697/the-north-face-yumiori-off-peak-full-zip-jacket-womens" 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="vamU4Ky2CB4QQda8nfrvm4" name="the north face yumiori jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vamU4Ky2CB4QQda8nfrvm4-1920-80.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C00697/the-north-face-yumiori-off-peak-full-zip-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ac5c9428-d472-11f1-a16a-91d15f768d7f" data-action="Deal Block" data-label="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension48="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension25="$74">Yumiori Off Peak Full-Zip Jacket - Women's: was $150 now $74</a></strong><br />The North Face's Yumiori fleece is a perfect hiking-slash-everyday fleece. Smartphones fit snugly into the chest pocket, one zipper even doubles as a hair tie, and it's finished with durable water repellent.<a class="view-deal button" href="https://www.rei.com/product/C00697/the-north-face-yumiori-off-peak-full-zip-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ac5c9428-d472-11f1-a16a-91d15f768d7f" data-action="Deal Block" data-label="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension48="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension25="$74">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c9496-d472-11f1-921d-055d5d5c368c" data-action="Deal Block" data-label="Antora Jacket (Women's)" data-dimension48="Antora Jacket (Women's)" data-dimension25="$91" href="https://www.amazon.com/dp/B0F97WG8SQ?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:731px;"><p class="vanilla-image-block" style="padding-top:205.20%;"><img id="bN5BuTC38YdrnSkcwmxwpg" name="Antora Jacket (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bN5BuTC38YdrnSkcwmxwpg-1920-80.jpg" mos="" align="middle" fullscreen="" width="731" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0F97WG8SQ?" target="_blank" rel="nofollow" data-dimension112="ac5c9496-d472-11f1-921d-055d5d5c368c" data-action="Deal Block" data-label="Antora Jacket (Women's)" data-dimension48="Antora Jacket (Women's)" data-dimension25="$91">Antora Jacket (Women's): was $130 now $91</a></strong><br />$91 is a great deal for this lightweight, weather-resistant shell. A core piece of outerwear no one should leave home without, the Antora Jacket boasts impressive rain-repellent capabilities. A drawstring-adjustable hood provides extra H2O protection, while a storm flap protects the main zipper from seepage during downpours. More importantly, as far as rain shells go, few can match the style factor of the Antora. <a class="view-deal button" href="https://www.amazon.com/dp/B0F97WG8SQ?" target="_blank" rel="nofollow" data-dimension112="ac5c9496-d472-11f1-921d-055d5d5c368c" data-action="Deal Block" data-label="Antora Jacket (Women's)" data-dimension48="Antora Jacket (Women's)" data-dimension25="$91">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c950e-d472-11f1-af0b-411f148a634c" data-action="Deal Block" data-label="R1 Pullover (Women's)" data-dimension48="R1 Pullover (Women's)" data-dimension25="$107" href="https://www.rei.com/product/242323/patagonia-r1-pullover-womens" 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="bre5ZuSFLvwfm5qxrkvwTm" name="patagonia r1 pullover" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bre5ZuSFLvwfm5qxrkvwTm-1920-80.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/242323/patagonia-r1-pullover-womens" target="_blank" rel="nofollow" data-dimension112="ac5c950e-d472-11f1-af0b-411f148a634c" data-action="Deal Block" data-label="R1 Pullover (Women's)" data-dimension48="R1 Pullover (Women's)" data-dimension25="$107">R1 Pullover (Women's): was $155 now $107</a></strong><br />The Patagonia R1 Pullover is a midlayer, meaning it's intended to be worn between a thermal base layer and an outer waterproof or windproof jacket like the Patagonia Houdini. <a class="view-deal button" href="https://www.rei.com/product/242323/patagonia-r1-pullover-womens" target="_blank" rel="nofollow" data-dimension112="ac5c950e-d472-11f1-af0b-411f148a634c" data-action="Deal Block" data-label="R1 Pullover (Women's)" data-dimension48="R1 Pullover (Women's)" data-dimension25="$107">View Deal</a></p></div><div class="product"><a data-dimension112="ac5c9586-d472-11f1-a255-9f68d50876bf" data-action="Deal Block" data-label="Arctic Parka (Women's)" data-dimension48="Arctic Parka (Women's)" data-dimension25="$350" href="https://www.amazon.com/North-Face-Womens-Arctic-Parka/dp/B0DSQ5M945" 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:192.34%;"><img id="JnwKQnbwffvW93sFWc4647" name="Arctic Parka (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/JnwKQnbwffvW93sFWc4647-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1306" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/North-Face-Womens-Arctic-Parka/dp/B0DSQ5M945" target="_blank" rel="nofollow" data-dimension112="ac5c9586-d472-11f1-a255-9f68d50876bf" data-action="Deal Block" data-label="Arctic Parka (Women's)" data-dimension48="Arctic Parka (Women's)" data-dimension25="$350">Arctic Parka (Women's): was $400 now $350</a></strong><br />When only the warmest coat will do, grab this Arctic Parka from The North Face. It's packed with 600-fill waterfowl down insulation, but is lightweight and packs away easily when the weather changes.<a class="view-deal button" href="https://www.amazon.com/North-Face-Womens-Arctic-Parka/dp/B0DSQ5M945" target="_blank" rel="nofollow" data-dimension112="ac5c9586-d472-11f1-a255-9f68d50876bf" data-action="Deal Block" data-label="Arctic Parka (Women's)" data-dimension48="Arctic Parka (Women's)" data-dimension25="$350">View Deal</a></p></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I’m a personal trainer over 40, and these are the exercises I do to maintain my hip strength and mobility ]]></title>
                                                                                                <dc:content><![CDATA[ <p>For someone who’s been active for the better part of my life, I’ve been lucky when it comes to injuries. I definitely want to keep that luck going as I get older. </p><p>That’s why much of my recent training has revolved around not only overall strength, but mobility and stability too. Your hips play a crucial role in all of those aspects, and if you want a body that can run, climb stairs, and balance when you’re 65, you’ll need to focus on it well before then. </p><p>The following four exercises have become a mainstay in my routine. They’ve led me to easier squats and faster runs for sure, but most importantly, they’ve improved my stability and helped me to maintain a good range of motion.</p><p>All you’ll need for these exercises is a single <a href="https://www.tomsguide.com/wellness/fitness/best-adjustable-dumbbells"><u>dumbbell</u></a>, a looped resistance band, and a yoga mat. Try them during your next workout, even if you’re under (or over) the 40 mark.</p><h2 id="how-to-do-the-four-exercises">How to do the four exercises</h2><p>Before starting any new workout or activity, be sure to check in with your doctor first. They may caution against certain movements or exercises based on your health history. </p><p>A few of these exercises may be challenging for beginners. A certified personal trainer can help you learn how to do them properly or give you modifications if needed. Incorrect form can cause pain or injury, so don’t hesitate to ask for guidance if you’re unsure.  </p><p>A good dumbbell or resistance band weight will allow you to do all of the reps in a set without needing to rest, but will leave you feeling fatigued by the end. If you can speed through a set without issue, go heavier. If you can only do a few reps before needing a break, go lighter. You may want to use different weights depending on the exercise, so if you have a few dumbbells at your disposal, keep them within reach during this workout. </p><p>Complete 3 full sets of each exercise before moving on to the next. As you get stronger and more conditioned, you might want to consider adding more sets or using heavier weights. However, make sure you’re always moving with proper form. </p><p>Beginners may need to start with fewer reps and sets. If you’ve just started to work out regularly, do the lower end of each listed rep range and gradually increase when you feel ready. </p><p>These exercises should cause muscle fatigue but never sharp pain. If you feel sharp pain at any point, stop immediately and see a doctor before continuing. </p><p>Here’s how to do the exercises:</p><h3 class="article-body__section" id="section-1-banded-clamshells"><span>1. Banded clamshells</span></h3><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/InAOx0qA9EE" allowfullscreen=""></iframe></div></div><ul><li>Place a looped resistance band around your legs, slightly above the knees.</li><li>Lie on your left side with your hips and knees stacked on top of each other.</li><li>Rotate your right knee towards the sky, keeping your hips stacked and feet connected.</li><li>Pause briefly.</li><li>Lower your right knee back to the starting position.</li><li>Continue for 12-15 reps, then repeat on the other side.</li></ul><h3 class="article-body__section" id="section-2-goblet-sumo-squat"><span>2. Goblet sumo squat</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/bzkE4JRfgQc" allowfullscreen=""></iframe></div></div><ul><li>Stand tall with your feet slightly wider than shoulder width apart.</li><li>Turn your toes out slightly.</li><li>Pick up a dumbbell and hold it at chest level.</li><li>Hinge your hips behind you, bend your knees, and lower your tailbone towards the ground.</li><li>Pause briefly.</li><li>Stand back up.</li><li>Continue for 10-12 reps.</li></ul><h3 class="article-body__section" id="section-3-lateral-lunges"><span>3. Lateral lunges</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/pjIq2m9XsVE" allowfullscreen=""></iframe></div></div><ul><li>Stand tall with your feet hip-width apart.</li><li>Hold a dumbbell in your right hand.</li><li>Step your left foot out to your side, keeping your toes forward.</li><li>Bend your left knee and lower your hips toward the ground, keeping your right leg straight.</li><li>Push off your left foot and return to the starting position.</li><li>Continue for 10-12 reps, then repeat on the other side.</li></ul><h3 class="article-body__section" id="section-4-single-leg-glute-bridge"><span>4. Single-leg glute bridge</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/sVfp4LN9niA" allowfullscreen=""></iframe></div></div><ul><li>Lie on your back with your knees bent and feet flat on the floor.</li><li>Lift your left knee to a tabletop position.</li><li>Push your right foot into the floor and lift your hips off the mat, keeping your hips square.</li><li>Pause briefly.</li><li>Lower your hips back to the mat.</li><li>Continue for 12-15 reps, then repeat on the other side.</li></ul><h2 id="benefits-of-the-four-exercises">Benefits of the four exercises</h2><p>This routine strengthens key muscle groups in the hips and lower body, including the glutes, hip abductors, hip adductors, quads, and hamstrings.</p><p>The banded clamshell, lateral lunge, and single-leg glute bridge are all performed unilaterally (or one side at a time), meaning muscle groups on each side must work independently of the other. This can help you identify and correct any strength imbalances, leading to better overall balance and stability. </p><p>Performing a sumo squat with the dumbbell held in a goblet position not only makes the exercise more challenging, but it also requires a greater effort from your deep core. Strengthening these muscles is vital for proper balance and full-body support. </p><p>As with any exercise program, pair this workout with a proper warm-up, cool-down, and stretching routine to maximize the benefits. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.js" async=""></script><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/workouts/im-a-personal-trainer-over-40-and-these-are-the-exercises-i-do-to-maintain-my-hip-strength-and-mobility</link>
                                                                            <description>
                            <![CDATA[ I'm a personal trainer, and these are the exercises I do to maintain my hip strength and mobility ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">KLrDgnTd5R9nRXNxoJp494</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/mYJPmpQk8g3AvP8tddg54D-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 30 Oct 2026 08: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-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/mYJPmpQk8g3AvP8tddg54D-1920-80.jpg">
                                                            <media:credit><![CDATA[Getty Images/ Iparraguirre Recio]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a 40 year old woman stretching]]></media:description>                                                            <media:text><![CDATA[a 40 year old woman stretching]]></media:text>
                                <media:title type="plain"><![CDATA[a 40 year old woman stretching]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/mYJPmpQk8g3AvP8tddg54D-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>For someone who’s been active for the better part of my life, I’ve been lucky when it comes to injuries. I definitely want to keep that luck going as I get older. </p><p>That’s why much of my recent training has revolved around not only overall strength, but mobility and stability too. Your hips play a crucial role in all of those aspects, and if you want a body that can run, climb stairs, and balance when you’re 65, you’ll need to focus on it well before then. </p><p>The following four exercises have become a mainstay in my routine. They’ve led me to easier squats and faster runs for sure, but most importantly, they’ve improved my stability and helped me to maintain a good range of motion.</p><p>All you’ll need for these exercises is a single <a href="https://www.tomsguide.com/wellness/fitness/best-adjustable-dumbbells"><u>dumbbell</u></a>, a looped resistance band, and a yoga mat. Try them during your next workout, even if you’re under (or over) the 40 mark.</p><h2 id="how-to-do-the-four-exercises">How to do the four exercises</h2><p>Before starting any new workout or activity, be sure to check in with your doctor first. They may caution against certain movements or exercises based on your health history. </p><p>A few of these exercises may be challenging for beginners. A certified personal trainer can help you learn how to do them properly or give you modifications if needed. Incorrect form can cause pain or injury, so don’t hesitate to ask for guidance if you’re unsure.  </p><p>A good dumbbell or resistance band weight will allow you to do all of the reps in a set without needing to rest, but will leave you feeling fatigued by the end. If you can speed through a set without issue, go heavier. If you can only do a few reps before needing a break, go lighter. You may want to use different weights depending on the exercise, so if you have a few dumbbells at your disposal, keep them within reach during this workout. </p><p>Complete 3 full sets of each exercise before moving on to the next. As you get stronger and more conditioned, you might want to consider adding more sets or using heavier weights. However, make sure you’re always moving with proper form. </p><p>Beginners may need to start with fewer reps and sets. If you’ve just started to work out regularly, do the lower end of each listed rep range and gradually increase when you feel ready. </p><p>These exercises should cause muscle fatigue but never sharp pain. If you feel sharp pain at any point, stop immediately and see a doctor before continuing. </p><p>Here’s how to do the exercises:</p><h3 class="article-body__section" id="section-1-banded-clamshells"><span>1. Banded clamshells</span></h3><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/InAOx0qA9EE" allowfullscreen=""></iframe></div></div><ul><li>Place a looped resistance band around your legs, slightly above the knees.</li><li>Lie on your left side with your hips and knees stacked on top of each other.</li><li>Rotate your right knee towards the sky, keeping your hips stacked and feet connected.</li><li>Pause briefly.</li><li>Lower your right knee back to the starting position.</li><li>Continue for 12-15 reps, then repeat on the other side.</li></ul><h3 class="article-body__section" id="section-2-goblet-sumo-squat"><span>2. Goblet sumo squat</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/bzkE4JRfgQc" allowfullscreen=""></iframe></div></div><ul><li>Stand tall with your feet slightly wider than shoulder width apart.</li><li>Turn your toes out slightly.</li><li>Pick up a dumbbell and hold it at chest level.</li><li>Hinge your hips behind you, bend your knees, and lower your tailbone towards the ground.</li><li>Pause briefly.</li><li>Stand back up.</li><li>Continue for 10-12 reps.</li></ul><h3 class="article-body__section" id="section-3-lateral-lunges"><span>3. Lateral lunges</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/pjIq2m9XsVE" allowfullscreen=""></iframe></div></div><ul><li>Stand tall with your feet hip-width apart.</li><li>Hold a dumbbell in your right hand.</li><li>Step your left foot out to your side, keeping your toes forward.</li><li>Bend your left knee and lower your hips toward the ground, keeping your right leg straight.</li><li>Push off your left foot and return to the starting position.</li><li>Continue for 10-12 reps, then repeat on the other side.</li></ul><h3 class="article-body__section" id="section-4-single-leg-glute-bridge"><span>4. Single-leg glute bridge</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/sVfp4LN9niA" allowfullscreen=""></iframe></div></div><ul><li>Lie on your back with your knees bent and feet flat on the floor.</li><li>Lift your left knee to a tabletop position.</li><li>Push your right foot into the floor and lift your hips off the mat, keeping your hips square.</li><li>Pause briefly.</li><li>Lower your hips back to the mat.</li><li>Continue for 12-15 reps, then repeat on the other side.</li></ul><h2 id="benefits-of-the-four-exercises">Benefits of the four exercises</h2><p>This routine strengthens key muscle groups in the hips and lower body, including the glutes, hip abductors, hip adductors, quads, and hamstrings.</p><p>The banded clamshell, lateral lunge, and single-leg glute bridge are all performed unilaterally (or one side at a time), meaning muscle groups on each side must work independently of the other. This can help you identify and correct any strength imbalances, leading to better overall balance and stability. </p><p>Performing a sumo squat with the dumbbell held in a goblet position not only makes the exercise more challenging, but it also requires a greater effort from your deep core. Strengthening these muscles is vital for proper balance and full-body support. </p><p>As with any exercise program, pair this workout with a proper warm-up, cool-down, and stretching routine to maximize the benefits. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.js" async=""></script><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I just went hands-on with the Ultrahuman Ring Pro — 7 things to know about this subscription-free Oura rival ]]></title>
                                                                                                <dc:content><![CDATA[ <p>When Ultrahuman first announced its new <a href="https://www.tomsguide.com/wellness/smart-rings/the-ultrahuman-ring-pro-is-a-flagship-oura-ring-4-competitor-but-not-everyone-will-be-able-to-buy-it">flagship Ring Pro</a> last February, we didn’t know whether the wearable would ultimately go on sale in the U.S. because of ongoing litigation with U.S.-based rival Oura. </p><p>Then, in March, Ultrahuman <a href="https://www.tomsguide.com/wellness/smart-rings/bad-news-for-oura-the-subscription-free-ultrahuman-ring-pro-is-officially-coming-to-the-u-s">opened preorders</a> for the Ring Pro to U.S. customers. Now, in the final week of October, the Ultrahuman Ring Pro has officially hit U.S. store shelves at major retailers like Best Buy and <a href="https://www.amazon.com/Ultrahuman-Subscription-Recovery-Titanium-Charging/dp/B0H1N5VLSN/" target="_blank" rel="nofollow">Amazon for $479</a>. </p><p>But is the Ultrahuman Ring Pro worth the hype? I’ve been wearing one for a few days — full review coming soon — and I already think it’s a seriously strong competitor to the <a href="https://www.tomsguide.com/wellness/smart-rings/oura-ring-5-hands-on-review-ive-worn-the-worlds-smallest-smart-ring-for-a-week-and-it-changes-fitness-tracking-forever">Oura Ring 5</a>, the <a href="https://www.tomsguide.com/wellness/fitness-trackers/best-smart-rings">best smart ring</a> in 2026.</p><p>With that in mind, here are the seven most important things you need to know about the Ultrahuman Ring Pro. </p><h3 class="article-body__section" id="section-1-it-s-been-completely-redesigned-to-avoid-oura-s-legal-wrath"><span>1. It's been completely redesigned to avoid Oura's (legal) wrath</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="vSWzrVEF53RoaE5tBmpJSL" name="UltrahumanPro-05" alt="Close-up of the flagship Ultrahuman Ring Pro, a direct rival to the Oura Ring 5" src="https://cdn.mos.cms.futurecdn.net/vSWzrVEF53RoaE5tBmpJSL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>The Ultrahuman Ring Pro features a unique unibody design that's purpose-built not only to withstand daily wear but also to avoid infringing on any of Oura's existing patents. As a reminder, <a href="https://www.tomsguide.com/wellness/smart-rings/oura-lawsuit-bans-rival-ultrahuman-in-the-us-what-that-means-for-your-smart-ring-and-the-best-alternatives">Oura successfully litigated</a> to keep the <a href="https://www.tomsguide.com/reviews/ultrahuman-ring-air-review-a-lighter-fitness-tracking-ring-without-a-subscription">Ultrahuman Ring Air</a>, the Pro's predecessor, off U.S. store shelves in 2025 for patent infringements.</p><p>However, when I spoke with  Mohit Kumar, the founder and CEO of Ultrahuman, earlier this year, he seemed confident in his team's reworked design for the newer model.</p><p>"We went through the [U.S.] <a href="https://www.ecfr.gov/current/title-19/chapter-I/part-177" target="_blank">Customs procedure 177</a> to get the device approved, noted Kumar. " We took the right path to make sure that the design is approved by (U.S.) Customs, and they officially issue an order that says, 'This is a design which is unique and non-infringing, for the patent which Oura holds.'"</p><p>Another benefit of the updated design: It features Ultrahuman's "ProRelease Technology," a safety feature that makes it relatively easy for emergency responders or medical professionals to cut the ring off for any reason (like a faulty, <a href="https://www.tomsguide.com/wellness/smart-rings/samsung-galaxy-ring-owner-reportedly-hospitalized-after-it-swells-wont-be-wearing-a-smart-ring-ever-again">swollen battery</a>). </p><h3 class="article-body__section" id="section-2-it-s-pricier-than-the-oura-ring-5-but"><span>2. It’s pricier than the Oura Ring 5, but…</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="TL9Zrw7F6ivgawPynUNXqL" name="UltrahumanPro-03" alt="Close-up of the flagship Ultrahuman Ring Pro, a direct rival to the Oura Ring 5" src="https://cdn.mos.cms.futurecdn.net/TL9Zrw7F6ivgawPynUNXqL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>The Ultrahuman Ring <a href="https://www.ultrahuman.com/us/ring-pro/buy/" target="_blank" rel="nofollow">starts at $479</a>, which is $79 more than the starting cost of the Oura Ring 5 (more on that in a second). It's available in four finishes, including gold, silver, black, and titanium, with sizes ranging from five to 14.</p><p>The $479 covers not only the ring but also the cost of Ultrahuman's swanky/handy Pro Charging case (further details on that too, below).  </p><h3 class="article-body__section" id="section-3-core-features-are-subscription-free"><span>3. Core features are subscription-free</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="RfHscgJnXLNHqYh4f9m5cL" name="UltrahumanPro-08" alt="Close-up of the flagship Ultrahuman Ring Pro, a direct rival to the Oura Ring 5" src="https://cdn.mos.cms.futurecdn.net/RfHscgJnXLNHqYh4f9m5cL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>Despite a higher up-front cost compared to the Oura Ring 5, the Ultrahuman Ring Pro is a better value after the first ~14 months of ownership. This is because Oura requires users to sign up for a subscription to use their smart ring for $5.99 a month or $69.99 a year.</p><p>Ultrahuman, on the other hand/finger, takes a more wallet-friendly, subscription-free approach to wellness tracking, which is perhaps the most notable difference between the two brands.  </p><h3 class="article-body__section" id="section-4-it-s-thicker-and-heavier-than-other-smart-rings"><span>4. It’s thicker and heavier than other smart rings</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.21%;"><img id="ahRhDG2EVhYPFAUBPPjnmL" name="UltrahumanPro-02" alt="Close-up of the flagship Ultrahuman Ring Pro, a direct rival to the Oura Ring 5" src="https://cdn.mos.cms.futurecdn.net/ahRhDG2EVhYPFAUBPPjnmL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1439" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>The Ultrahuman Ring Pro is noticeably heavier than the Oura Ring 5. My size 11 silver Ultrahuman Ring Pro weighs 4.52 g versus ~2.5 g for the comparable Oura Ring 5. The latest Ultrahuman flagship is also thicker than its rival...then again, Oura's latest is one of the smallest, lightest smart rings in the world. </p><p>The Ultrahuman Ring Pro has a thickness of 2.6mm around the band and ~4.8mm at the sensors, making it thicker (and heavier) than other popular smart rings I've tested/demoed, too, like the <a href="https://www.tomsguide.com/wellness/smart-rings/ringconn-gen-2-air-review-this-budget-smart-ring-beats-the-oura-ring-4-in-three-big-ways">RingConn Gen 2 Air.</a></p><p>That said, after 24 hours of wearing the Ring Pro, I hardly notice it on my left index finger, and this is coming from someone who doesn't usually rock rings. That said, let's see if my tune changes over the coming weeks. </p><h3 class="article-body__section" id="section-5-ultrahuman-reworked-the-heart-rate-sensor-for-better-accuracy"><span>5. Ultrahuman reworked the heart rate sensor for better accuracy </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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="S4Mq8jK2gpswfPmSuP2j8L" name="UltrahumanPro-01" alt="Close-up of the flagship Ultrahuman Ring Pro, a direct rival to the Oura Ring 5" src="https://cdn.mos.cms.futurecdn.net/S4Mq8jK2gpswfPmSuP2j8L-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>In addition to a redesigned body, the Ultrahuman Ring Pro features an overhauled heart rate sensor with added processing power for more accurate cardiovascular, sleep, and recovery insights. The updated processor additionally supports on-device machine learning capabilities. </p><p>But how does the heart rate accuracy of the Ultrahuman Ring Pro compare to the competition? I intend to find out, not just versus the best smart rings but some of the <a href="https://www.tomsguide.com/us/best-fitness-trackers,review-2066.html">best fitness trackers</a> too. </p><h3 class="article-body__section" id="section-6-it-gets-up-to-15-days-of-battery-per-charge"><span>6. It gets up to 15 days of battery per charge</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="8heHGGXQX2b2wW8zBJo5WL" name="UltrahumanPro-07" alt="Close-up of the flagship Ultrahuman Ring Pro, a direct rival to the Oura Ring 5" src="https://cdn.mos.cms.futurecdn.net/8heHGGXQX2b2wW8zBJo5WL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>The Oura Ring 5 promises up to a respectable nine days of battery per charge, even if in reality, that number is closer to seven or eight. Meanwhile, the Ultrahuman Ring Pro blows its Oura rival away with claims of up to 15 days of battery life per charge.</p><p>Will it really last that long? You can also count on me finding that out! But given its heftier-by-comparison footprint, there's a good shot the new Ultrahuman has a larger-capacity battery than the 22 mAh one in the latest Oura Ring. </p><h3 class="article-body__section" id="section-7-the-pro-case-extends-battery-life-to-45-days"><span>7. The Pro case extends battery life to 45 days </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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AS9r9UsMaHjRP2Gx2srbrL" name="UltrahumanPro-11" alt="Close-up of the flagship Ultrahuman Ring Pro, a direct rival to the Oura Ring 5" src="https://cdn.mos.cms.futurecdn.net/AS9r9UsMaHjRP2Gx2srbrL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>Finally, remember that free charging case I mentioned earlier? It's perhaps the nicest smart ring case I've encountered. The exterior shell is all-metal with a no-slip silicone bottom. It opens and closes clam-shell-style with a seriously satisfying snap. </p><p>LEDs on the side reflect the remaining battery capacity of the case, which can fully recharge the Ultrahuman Ring Pro two times, pushing its battery life to a max of 45 days without needing to hit a wall outlet. </p><p>But wait, there's more. The Pro Case doubles as a connection point for updating the Ultrahuman Ring Pro's firmware, and it supports haptic feedback and audible alerts for things like a fully charged battery.  </p><p>What are your thoughts on the newly available (in the U.S.) Ultrahuman Ring Pro? Would you consider it over the Oura Ring 5, knowing that it's subscription-free? And besides the latest Oura Ring, what should I test the Ultrahuman Ring Pro against? Shout out your thoughts below! </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-evBP6e"></div>                            </div>                            <script src="https://kwizly.com/embed/evBP6e.js" async=""></script><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><strong></strong><a href="https://www.tomsguide.com/wellness/smart-rings/i-ditched-alcohol-for-30-days-and-my-oura-ring-5-showed-one-surprising-change"><strong>I ditched alcohol for 30 days — and my Oura Ring 5 showed one surprising change</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smart-rings/i-just-went-hands-on-with-the-new-circular-ring-3-and-it-beats-the-oura-ring-5-in-3-big-ways"><strong>I just went hands-on with the new Circular Ring 3 — and it beats the Oura Ring 5 in 3 big ways</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smart-rings/garmin-looks-to-be-developing-a-smart-ring-heres-what-we-know-so-far"><strong>Garmin looks to be developing a smart ring: Here’s what we know so far</strong></a><strong></strong></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/smart-rings/i-just-went-hands-on-with-the-ultrahuman-ring-pro-7-things-to-know-about-this-subscription-free-oura-rival</link>
                                                                            <description>
                            <![CDATA[ I've been wearing the flagship Ultrahuman Ring Pro for just a few days, but I already think it’s a seriously strong competitor to the Oura Ring 5. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">pxHPheQVtTz5qt3he23kUm</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/qh4Emf8Q9HA8oEgPFVLPcL-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 30 Oct 2026 06:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Smart Rings]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                                                                <author><![CDATA[ dan.bracaglia@futurenet.com (Dan Bracaglia) ]]></author>                    <dc:creator><![CDATA[ Dan Bracaglia ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/3Ev8EFrheNxPemMWSBaKcK-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;&lt;br&gt;&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/qh4Emf8Q9HA8oEgPFVLPcL-1920-80.jpg">
                                                            <media:credit><![CDATA[Dan Bracaglia/Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Close-up of the flagship Ultrahuman Ring Pro, a direct rival to the Oura Ring 5]]></media:description>                                                            <media:text><![CDATA[Close-up of the flagship Ultrahuman Ring Pro, a direct rival to the Oura Ring 5]]></media:text>
                                <media:title type="plain"><![CDATA[Close-up of the flagship Ultrahuman Ring Pro, a direct rival to the Oura Ring 5]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/qh4Emf8Q9HA8oEgPFVLPcL-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>When Ultrahuman first announced its new <a href="https://www.tomsguide.com/wellness/smart-rings/the-ultrahuman-ring-pro-is-a-flagship-oura-ring-4-competitor-but-not-everyone-will-be-able-to-buy-it">flagship Ring Pro</a> last February, we didn’t know whether the wearable would ultimately go on sale in the U.S. because of ongoing litigation with U.S.-based rival Oura. </p><p>Then, in March, Ultrahuman <a href="https://www.tomsguide.com/wellness/smart-rings/bad-news-for-oura-the-subscription-free-ultrahuman-ring-pro-is-officially-coming-to-the-u-s">opened preorders</a> for the Ring Pro to U.S. customers. Now, in the final week of October, the Ultrahuman Ring Pro has officially hit U.S. store shelves at major retailers like Best Buy and <a href="https://www.amazon.com/Ultrahuman-Subscription-Recovery-Titanium-Charging/dp/B0H1N5VLSN/" target="_blank" rel="nofollow">Amazon for $479</a>. </p><p>But is the Ultrahuman Ring Pro worth the hype? I’ve been wearing one for a few days — full review coming soon — and I already think it’s a seriously strong competitor to the <a href="https://www.tomsguide.com/wellness/smart-rings/oura-ring-5-hands-on-review-ive-worn-the-worlds-smallest-smart-ring-for-a-week-and-it-changes-fitness-tracking-forever">Oura Ring 5</a>, the <a href="https://www.tomsguide.com/wellness/fitness-trackers/best-smart-rings">best smart ring</a> in 2026.</p><p>With that in mind, here are the seven most important things you need to know about the Ultrahuman Ring Pro. </p><h3 class="article-body__section" id="section-1-it-s-been-completely-redesigned-to-avoid-oura-s-legal-wrath"><span>1. It's been completely redesigned to avoid Oura's (legal) wrath</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="vSWzrVEF53RoaE5tBmpJSL" name="UltrahumanPro-05" alt="Close-up of the flagship Ultrahuman Ring Pro, a direct rival to the Oura Ring 5" src="https://cdn.mos.cms.futurecdn.net/vSWzrVEF53RoaE5tBmpJSL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>The Ultrahuman Ring Pro features a unique unibody design that's purpose-built not only to withstand daily wear but also to avoid infringing on any of Oura's existing patents. As a reminder, <a href="https://www.tomsguide.com/wellness/smart-rings/oura-lawsuit-bans-rival-ultrahuman-in-the-us-what-that-means-for-your-smart-ring-and-the-best-alternatives">Oura successfully litigated</a> to keep the <a href="https://www.tomsguide.com/reviews/ultrahuman-ring-air-review-a-lighter-fitness-tracking-ring-without-a-subscription">Ultrahuman Ring Air</a>, the Pro's predecessor, off U.S. store shelves in 2025 for patent infringements.</p><p>However, when I spoke with  Mohit Kumar, the founder and CEO of Ultrahuman, earlier this year, he seemed confident in his team's reworked design for the newer model.</p><p>"We went through the [U.S.] <a href="https://www.ecfr.gov/current/title-19/chapter-I/part-177" target="_blank">Customs procedure 177</a> to get the device approved, noted Kumar. " We took the right path to make sure that the design is approved by (U.S.) Customs, and they officially issue an order that says, 'This is a design which is unique and non-infringing, for the patent which Oura holds.'"</p><p>Another benefit of the updated design: It features Ultrahuman's "ProRelease Technology," a safety feature that makes it relatively easy for emergency responders or medical professionals to cut the ring off for any reason (like a faulty, <a href="https://www.tomsguide.com/wellness/smart-rings/samsung-galaxy-ring-owner-reportedly-hospitalized-after-it-swells-wont-be-wearing-a-smart-ring-ever-again">swollen battery</a>). </p><h3 class="article-body__section" id="section-2-it-s-pricier-than-the-oura-ring-5-but"><span>2. It’s pricier than the Oura Ring 5, but…</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="TL9Zrw7F6ivgawPynUNXqL" name="UltrahumanPro-03" alt="Close-up of the flagship Ultrahuman Ring Pro, a direct rival to the Oura Ring 5" src="https://cdn.mos.cms.futurecdn.net/TL9Zrw7F6ivgawPynUNXqL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>The Ultrahuman Ring <a href="https://www.ultrahuman.com/us/ring-pro/buy/" target="_blank" rel="nofollow">starts at $479</a>, which is $79 more than the starting cost of the Oura Ring 5 (more on that in a second). It's available in four finishes, including gold, silver, black, and titanium, with sizes ranging from five to 14.</p><p>The $479 covers not only the ring but also the cost of Ultrahuman's swanky/handy Pro Charging case (further details on that too, below).  </p><h3 class="article-body__section" id="section-3-core-features-are-subscription-free"><span>3. Core features are subscription-free</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="RfHscgJnXLNHqYh4f9m5cL" name="UltrahumanPro-08" alt="Close-up of the flagship Ultrahuman Ring Pro, a direct rival to the Oura Ring 5" src="https://cdn.mos.cms.futurecdn.net/RfHscgJnXLNHqYh4f9m5cL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>Despite a higher up-front cost compared to the Oura Ring 5, the Ultrahuman Ring Pro is a better value after the first ~14 months of ownership. This is because Oura requires users to sign up for a subscription to use their smart ring for $5.99 a month or $69.99 a year.</p><p>Ultrahuman, on the other hand/finger, takes a more wallet-friendly, subscription-free approach to wellness tracking, which is perhaps the most notable difference between the two brands.  </p><h3 class="article-body__section" id="section-4-it-s-thicker-and-heavier-than-other-smart-rings"><span>4. It’s thicker and heavier than other smart rings</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.21%;"><img id="ahRhDG2EVhYPFAUBPPjnmL" name="UltrahumanPro-02" alt="Close-up of the flagship Ultrahuman Ring Pro, a direct rival to the Oura Ring 5" src="https://cdn.mos.cms.futurecdn.net/ahRhDG2EVhYPFAUBPPjnmL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1439" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>The Ultrahuman Ring Pro is noticeably heavier than the Oura Ring 5. My size 11 silver Ultrahuman Ring Pro weighs 4.52 g versus ~2.5 g for the comparable Oura Ring 5. The latest Ultrahuman flagship is also thicker than its rival...then again, Oura's latest is one of the smallest, lightest smart rings in the world. </p><p>The Ultrahuman Ring Pro has a thickness of 2.6mm around the band and ~4.8mm at the sensors, making it thicker (and heavier) than other popular smart rings I've tested/demoed, too, like the <a href="https://www.tomsguide.com/wellness/smart-rings/ringconn-gen-2-air-review-this-budget-smart-ring-beats-the-oura-ring-4-in-three-big-ways">RingConn Gen 2 Air.</a></p><p>That said, after 24 hours of wearing the Ring Pro, I hardly notice it on my left index finger, and this is coming from someone who doesn't usually rock rings. That said, let's see if my tune changes over the coming weeks. </p><h3 class="article-body__section" id="section-5-ultrahuman-reworked-the-heart-rate-sensor-for-better-accuracy"><span>5. Ultrahuman reworked the heart rate sensor for better accuracy </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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="S4Mq8jK2gpswfPmSuP2j8L" name="UltrahumanPro-01" alt="Close-up of the flagship Ultrahuman Ring Pro, a direct rival to the Oura Ring 5" src="https://cdn.mos.cms.futurecdn.net/S4Mq8jK2gpswfPmSuP2j8L-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>In addition to a redesigned body, the Ultrahuman Ring Pro features an overhauled heart rate sensor with added processing power for more accurate cardiovascular, sleep, and recovery insights. The updated processor additionally supports on-device machine learning capabilities. </p><p>But how does the heart rate accuracy of the Ultrahuman Ring Pro compare to the competition? I intend to find out, not just versus the best smart rings but some of the <a href="https://www.tomsguide.com/us/best-fitness-trackers,review-2066.html">best fitness trackers</a> too. </p><h3 class="article-body__section" id="section-6-it-gets-up-to-15-days-of-battery-per-charge"><span>6. It gets up to 15 days of battery per charge</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="8heHGGXQX2b2wW8zBJo5WL" name="UltrahumanPro-07" alt="Close-up of the flagship Ultrahuman Ring Pro, a direct rival to the Oura Ring 5" src="https://cdn.mos.cms.futurecdn.net/8heHGGXQX2b2wW8zBJo5WL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>The Oura Ring 5 promises up to a respectable nine days of battery per charge, even if in reality, that number is closer to seven or eight. Meanwhile, the Ultrahuman Ring Pro blows its Oura rival away with claims of up to 15 days of battery life per charge.</p><p>Will it really last that long? You can also count on me finding that out! But given its heftier-by-comparison footprint, there's a good shot the new Ultrahuman has a larger-capacity battery than the 22 mAh one in the latest Oura Ring. </p><h3 class="article-body__section" id="section-7-the-pro-case-extends-battery-life-to-45-days"><span>7. The Pro case extends battery life to 45 days </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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AS9r9UsMaHjRP2Gx2srbrL" name="UltrahumanPro-11" alt="Close-up of the flagship Ultrahuman Ring Pro, a direct rival to the Oura Ring 5" src="https://cdn.mos.cms.futurecdn.net/AS9r9UsMaHjRP2Gx2srbrL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Dan Bracaglia/Tom's Guide)</span></figcaption></figure><p>Finally, remember that free charging case I mentioned earlier? It's perhaps the nicest smart ring case I've encountered. The exterior shell is all-metal with a no-slip silicone bottom. It opens and closes clam-shell-style with a seriously satisfying snap. </p><p>LEDs on the side reflect the remaining battery capacity of the case, which can fully recharge the Ultrahuman Ring Pro two times, pushing its battery life to a max of 45 days without needing to hit a wall outlet. </p><p>But wait, there's more. The Pro Case doubles as a connection point for updating the Ultrahuman Ring Pro's firmware, and it supports haptic feedback and audible alerts for things like a fully charged battery.  </p><p>What are your thoughts on the newly available (in the U.S.) Ultrahuman Ring Pro? Would you consider it over the Oura Ring 5, knowing that it's subscription-free? And besides the latest Oura Ring, what should I test the Ultrahuman Ring Pro against? Shout out your thoughts below! </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-evBP6e"></div>                            </div>                            <script src="https://kwizly.com/embed/evBP6e.js" async=""></script><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><strong></strong><a href="https://www.tomsguide.com/wellness/smart-rings/i-ditched-alcohol-for-30-days-and-my-oura-ring-5-showed-one-surprising-change"><strong>I ditched alcohol for 30 days — and my Oura Ring 5 showed one surprising change</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smart-rings/i-just-went-hands-on-with-the-new-circular-ring-3-and-it-beats-the-oura-ring-5-in-3-big-ways"><strong>I just went hands-on with the new Circular Ring 3 — and it beats the Oura Ring 5 in 3 big ways</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/smart-rings/garmin-looks-to-be-developing-a-smart-ring-heres-what-we-know-so-far"><strong>Garmin looks to be developing a smart ring: Here’s what we know so far</strong></a><strong></strong></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ These Skechers are the best slip-in shoes we've tested — and they're on sale for £39 at Amazon ]]></title>
                                                                                                <dc:content><![CDATA[ <p>No one likes stopping to tie their shoes. And no one likes uncomfortable walking shoes, either. But with this Skechers deal, you won't have to deal with either of those problems ever again.</p><p>Right now the <a href="https://www.amazon.co.uk/Skechers-Womens-Slip-Summits-Dazzling/dp/B0B4T65TYG" target="_blank" rel="nofollow">Skechers Summits Dazzling Haze Sneakers are on sale from £39 at Amazon</a>. They're the <a href="https://www.tomsguide.com/best-picks/best-skechers-shoes-in-year">best Skechers</a> slip-ins we've tested, offering a supremely lightweight and comfortable stretchy fit. <strong>Note: </strong>prices vary depending on the size and colour you select, so check out the different colour options in your size to find the best deal for you.</p><ul><li><a href="https://www.amazon.co.uk/stores/page/DEE5E5D3-5D22-4BF2-BACF-5E3F9351F478" target="_blank" rel="nofollow"><strong>shop all Skechers deals at Amazon</strong></a></li></ul><div class="product"><a data-dimension112="360fe76e-d38e-11f1-b0d3-2f572da3eb2c" data-action="Deal Block" data-label="Summits Dazzling Haze Slip Ins (Women's)" data-dimension48="Summits Dazzling Haze Slip Ins (Women's)" data-dimension25="£39" href="https://www.amazon.co.uk/Skechers-Womens-Slip-Summits-Dazzling/dp/B0B4T65TYG" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1014px;"><p class="vanilla-image-block" style="padding-top:99.01%;"><img id="pSZ3kia4ASQrHBkvC9wUx7" name="Skechers_Slip_Ins_Dazzling_Haze.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pSZ3kia4ASQrHBkvC9wUx7-1920-80.jpg" mos="" align="middle" fullscreen="" width="1014" height="1004" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.co.uk/Skechers-Womens-Slip-Summits-Dazzling/dp/B0B4T65TYG" target="_blank" rel="nofollow" data-dimension112="360fe76e-d38e-11f1-b0d3-2f572da3eb2c" data-action="Deal Block" data-label="Summits Dazzling Haze Slip Ins (Women's)" data-dimension48="Summits Dazzling Haze Slip Ins (Women's)" data-dimension25="£39">Summits Dazzling Haze Slip Ins (Women's): was £75 now £39</a></strong><br />These are the best Skechers slip-ins we've tested, so they're the ones to get if you want a super easy way to put your shoes on. They're lightweight, stretchy and breathable. In our <a href="https://www.tomsguide.com/reviews/skechers-slip-in-summit">Skechers Slip Ins Dazzling Haze review</a>, we said they're perfect for low-impact activities like walking, light resistance training and dance cardio. <strong>Note: </strong>prices vary depending on the size and colour you select, so check out the different colour options in your size to find the best deal for you.<a class="view-deal button" href="https://www.amazon.co.uk/Skechers-Womens-Slip-Summits-Dazzling/dp/B0B4T65TYG" target="_blank" rel="nofollow" data-dimension112="360fe76e-d38e-11f1-b0d3-2f572da3eb2c" data-action="Deal Block" data-label="Summits Dazzling Haze Slip Ins (Women's)" data-dimension48="Summits Dazzling Haze Slip Ins (Women's)" data-dimension25="£39">View Deal</a></p></div><p>We gave these shoes an excellent 4-star rating in our <a href="https://www.tomsguide.com/reviews/skechers-slip-in-summit">Skechers Slip Ins Dazzling Haze review</a>, and they've been on our list of the <a href="https://www.tomsguide.com/best-picks/best-skechers-shoes-in-year">best Skechers</a> for many years running. And you don't just have to take my word for it; they're beloved by Amazon shoppers too, earning a 4.7-star rating based on over 21,000 reviews.</p><p>The stretchy fit makes them extremely comfortable even if you have wider feet, and they plush cushioning makes them feel velvety soft underfoot. For low-impact activities like walking, dance cardio or yoga, these shoes can't be beat.</p><p>With prices starting from £39, these shoes are a steal, so make sure to grab a pair if they're still available in your size.</p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness/these-skechers-are-the-best-slip-in-shoes-weve-tested-and-theyre-on-sale-for-gbp39-at-amazon</link>
                                                                            <description>
                            <![CDATA[ Hate stopping to tie your shoes? Get this huge discount on Skechers slip-ins while it's still available. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">KtP8DSh7A9M2GtGbX6oSdB</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/MiK6wk8LyCQmrJgYGZFtKm-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 29 Oct 2026 11:57:45 +0000</pubDate>                                                                                                                                <updated>Thu, 29 Oct 2026 12:59:38 +0000</updated>
                                                                                                                                            <category><![CDATA[Fitness]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                <author><![CDATA[ millie.daviswilliams@futurenet.com (Millie Davis-Williams) ]]></author>                    <dc:creator><![CDATA[ Millie Davis-Williams ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/WU6pa7hKuxs5ScCoqcXYWA-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Millie is a Deals Editor at Tom&#039;s Guide specializing in tech deals content. Based in London, Millie has spent a lifetime stubbornly refusing to pay full price on any possible purchase. She has years of searching for the best discounts on the latest and greatest phones, TVs and gadgets under her belt, and knows how to sort the best deals from the rest. Helping readers save on the products they want is her mission, whether it’s an Apple Watch or a new tablet.&lt;/p&gt;&lt;p&gt;Since working at Tom’s Guide, Millie has covered retail events like Prime Day, Black Friday and Cyber Monday extensively, meaning she knows the products readers are looking for and the best times of year to hit “purchase.”&lt;/p&gt;&lt;p&gt;When she’s not looking for discounts, Millie covers news and writes how-to articles about everything from phones, streaming devices, and headphones to apps and video games.&lt;/p&gt;&lt;p&gt;In her spare time, Millie enjoys reading, gaming on her Nintendo Switch and creating digital art. She’s also a fan of watching Disney movies and collecting plush (the latter having totally taken over her bedroom.)&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/MiK6wk8LyCQmrJgYGZFtKm-1920-80.jpg">
                                                            <media:credit><![CDATA[Skechers]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Skechers Summits Dazzling Haze slip-in sneakers]]></media:description>                                                            <media:text><![CDATA[Skechers Summits Dazzling Haze slip-in sneakers]]></media:text>
                                <media:title type="plain"><![CDATA[Skechers Summits Dazzling Haze slip-in sneakers]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/MiK6wk8LyCQmrJgYGZFtKm-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>No one likes stopping to tie their shoes. And no one likes uncomfortable walking shoes, either. But with this Skechers deal, you won't have to deal with either of those problems ever again.</p><p>Right now the <a href="https://www.amazon.co.uk/Skechers-Womens-Slip-Summits-Dazzling/dp/B0B4T65TYG" target="_blank" rel="nofollow">Skechers Summits Dazzling Haze Sneakers are on sale from £39 at Amazon</a>. They're the <a href="https://www.tomsguide.com/best-picks/best-skechers-shoes-in-year">best Skechers</a> slip-ins we've tested, offering a supremely lightweight and comfortable stretchy fit. <strong>Note: </strong>prices vary depending on the size and colour you select, so check out the different colour options in your size to find the best deal for you.</p><ul><li><a href="https://www.amazon.co.uk/stores/page/DEE5E5D3-5D22-4BF2-BACF-5E3F9351F478" target="_blank" rel="nofollow"><strong>shop all Skechers deals at Amazon</strong></a></li></ul><div class="product"><a data-dimension112="360fe76e-d38e-11f1-b0d3-2f572da3eb2c" data-action="Deal Block" data-label="Summits Dazzling Haze Slip Ins (Women's)" data-dimension48="Summits Dazzling Haze Slip Ins (Women's)" data-dimension25="£39" href="https://www.amazon.co.uk/Skechers-Womens-Slip-Summits-Dazzling/dp/B0B4T65TYG" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1014px;"><p class="vanilla-image-block" style="padding-top:99.01%;"><img id="pSZ3kia4ASQrHBkvC9wUx7" name="Skechers_Slip_Ins_Dazzling_Haze.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pSZ3kia4ASQrHBkvC9wUx7-1920-80.jpg" mos="" align="middle" fullscreen="" width="1014" height="1004" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.co.uk/Skechers-Womens-Slip-Summits-Dazzling/dp/B0B4T65TYG" target="_blank" rel="nofollow" data-dimension112="360fe76e-d38e-11f1-b0d3-2f572da3eb2c" data-action="Deal Block" data-label="Summits Dazzling Haze Slip Ins (Women's)" data-dimension48="Summits Dazzling Haze Slip Ins (Women's)" data-dimension25="£39">Summits Dazzling Haze Slip Ins (Women's): was £75 now £39</a></strong><br />These are the best Skechers slip-ins we've tested, so they're the ones to get if you want a super easy way to put your shoes on. They're lightweight, stretchy and breathable. In our <a href="https://www.tomsguide.com/reviews/skechers-slip-in-summit">Skechers Slip Ins Dazzling Haze review</a>, we said they're perfect for low-impact activities like walking, light resistance training and dance cardio. <strong>Note: </strong>prices vary depending on the size and colour you select, so check out the different colour options in your size to find the best deal for you.<a class="view-deal button" href="https://www.amazon.co.uk/Skechers-Womens-Slip-Summits-Dazzling/dp/B0B4T65TYG" target="_blank" rel="nofollow" data-dimension112="360fe76e-d38e-11f1-b0d3-2f572da3eb2c" data-action="Deal Block" data-label="Summits Dazzling Haze Slip Ins (Women's)" data-dimension48="Summits Dazzling Haze Slip Ins (Women's)" data-dimension25="£39">View Deal</a></p></div><p>We gave these shoes an excellent 4-star rating in our <a href="https://www.tomsguide.com/reviews/skechers-slip-in-summit">Skechers Slip Ins Dazzling Haze review</a>, and they've been on our list of the <a href="https://www.tomsguide.com/best-picks/best-skechers-shoes-in-year">best Skechers</a> for many years running. And you don't just have to take my word for it; they're beloved by Amazon shoppers too, earning a 4.7-star rating based on over 21,000 reviews.</p><p>The stretchy fit makes them extremely comfortable even if you have wider feet, and they plush cushioning makes them feel velvety soft underfoot. For low-impact activities like walking, dance cardio or yoga, these shoes can't be beat.</p><p>With prices starting from £39, these shoes are a steal, so make sure to grab a pair if they're still available in your size.</p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 'These 7 exercises improve joint range of motion, movement quality and overall mobility,' says a personal trainer ]]></title>
                                                                                                <dc:content><![CDATA[ <p>"These five exercises improve joint range of motion, movement quality, and overall mobility," says LJ, a master trainer at London's <a href="https://www.1rebel.com/" target="_blank" rel="nofollow">1Rebel</a>. And as a coach who teaches mobility classes every week, I have to agree they're some of my favorites.</p><p>You only need an exercise mat, nothing else. And while LJ doesn't specify sets, reps, or timings, I provide my recommendations below, plus some of the benefits LJ says you can expect. Check out the video, roll out your mat and get ready to feel loose and free again.</p><p>Here it is!</p><h2 id="watch-master-trainer-39-s-mobility-routine">Watch: Master trainer's 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/DeynHIkTUVz/" target="_blank">A post shared by Tom's Guide Fitness | Workout Tips &amp; Gear (@tomsguidefitness)</a></p><p>A photo posted by </p></blockquote></div><p>As a personal trainer myself, I would recommend programming 45 seconds on and 15 seconds off for 3-5 rounds. If you prefer to work with sets and reps, try 6-8 reps per side per move, and 2 sets of each movement. </p><ul><li><strong>Adductor rocks: </strong>Start on all fours, then extend one leg out to the side, foot flat and toes pointing forward. Keeping your spine neutral, rock your hips back towards your heel, then forward again, moving slowly and under control. <em><strong>Working: </strong></em>Adductors (inner thighs), plus hip mobility in the frontal plane. Great for runners, lifters and anyone who sits a lot. </li><li><strong>Scorpions: </strong>Lie face down with your arms out in a T. Swing one heel up and across your body toward the opposite hand, letting your hips rotate, then return and repeat on the other side.<strong> </strong><em><strong>Working</strong></em><em>: </em>Hip flexors and quads (front-of-hip stretch), spinal rotation and thoracic mobility, and glutes as you control the movement. </li><li><strong>Glute bridge to cross-body overhead reach: </strong>Lie on your back, knees bent, and drive through your heels into a glute bridge. At the top, reach one arm up and across your body overhead, then lower back down with control and alternate sides.<strong> </strong><em><strong>Working: </strong></em>Glutes and hamstrings for hip extension, plus core stability and thoracic rotation, combined with shoulder mobility through the overhead reach.</li><li><strong>Quadruped hip internal rotations: </strong>From all fours, lift one foot slightly off the floor and sweep your foot out to the side so the hip rotates inward, then return. Keep your torso still so the movement comes from the hip. <em><strong>Working</strong></em><em>: </em>Hip internal rotation, an often-neglected range that’s key for running, squatting and change of direction. It also challenges the deep hip rotators. </li><li><strong>Wall clock (shoulder arc): </strong>Stand side-on to a wall and place a forearm or hand against it. Slowly trace an arc with your arm, like moving across the numbers on a clock face, keeping your ribs down and shoulder blade moving smoothly.<strong> </strong><em><strong>Working:</strong></em><em> </em>Shoulder mobility and scapular control, targeting the rotator cuff and the muscles that stabilize the shoulder blade. Particularly useful for overhead work.</li><li><strong>Adductor half-kneeling rock with kettlebell/light weight: </strong>Start in a half-kneeling position with the front leg out to the side. Hold a kettlebell or light weight at your chest as a counterbalance, then rock your hips back and forth, keeping your chest tall. <em><strong>Working:</strong></em><em> </em>Adductor length and hip mobility under light load, plus core and glute engagement to stay stable. </li><li><strong>Prone swimmers:</strong><em> </em>Lie face down with your arms extended overhead and legs straight, forehead hovering just above the mat so your neck stays neutral. Lift your arms and legs slightly off the floor, then alternate opposite arm and leg using a flutter style of small, controlled movement. Keep your glutes engaged and avoid cranking your lower back. <em><strong>Working:</strong></em><em> </em>Spinal extensors (erector spinae) and glutes, plus the mid and lower traps and rear delts for shoulder and posture strength. It’s a great counter to desk-hunched postures.</li></ul><h2 id="what-happened-when-i-tried-it">What happened when I tried it</h2><p>Try to keep the reps similar for each move in each round, and work both sides of the body. If you choose equal-number rounds, you could complete the reps on one side only, then switch to the other side on the next round.</p><div><blockquote><p>I loved this routine, and it helped me feel far looser going into my day or my next workout. </p></blockquote></div><p>Some of these exercises I know already and use with clients; some were actually new to me, such as the glute bridge with overhead reach. I opted for two sets and 6-8 reps per side as a warm-up before coaching a mobility session, and I have since stolen them to use in my next class.</p><p>Combined, these exercises are brilliant for improving the range of motion in your joints and priming the muscles for exercise by increasing blood flow. Repeating these moves over time will improve posture, build range and bolster overall mobility, which means the quality of your movements during workouts should also improve. </p><p>As LJ mentions, you'll internally rotate your hips, strengthen the postural muscles in your back and even target stabilizing muscles like your hip flexors and rotator cuff (the RC includes a group of muscles that stabilize the shoulder joint and sit around the scapulae), which means you're building a body capable of withstanding injury through weakness or underuse/overuse.</p><p>If you're new to mobility or this type of routine, I strongly recommend taking it slowly and stopping if you experience any pain, especially if you have a health condition or injury. </p><p>I loved this routine, and it helped me feel far looser going into my day or my next workout. Let us know if it helps you, too.</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><p>If you suffer from tight hips or back pain, some (or all) of these moves might be useful for you to try, but <strong>stop and rest if you need to. </strong>And if you're unsure <a href="https://www.tomsguide.com/news/this-is-the-most-important-thing-to-do-when-working-your-abs-according-to-a-personal-trainer">how to engage your core properly</a>, this <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">short "bracing" routine</a> might be helpful before you start the routine, just to protect your lower back.</p><p>Move with control, remember to breathe and don't rush your reps. Also remember that training should make you feel good, so focus on what you enjoy about the routine and how it makes your body feel.</p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="vGnNDN" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-to-be-more-mobile-in-their-60s-and-70s-3-low-impact-exercises-you-should-start-with" target="_blank">I teach people to be more mobile in their 60s and 70s: 3 low-impact exercises you should start with</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/forget-burpees-the-pilates-burpee-is-beginner-friendly-and-low-impact-and-youll-love-it" target="_blank">Forget burpees —the 'Pilates burpee' is beginner-friendly and low-impact (and you’ll love it)</a></li><li><a href="https://www.tomsguide.com/wellness/workouts/a-yoga-instructor-says-this-is-the-5-minute-yoga-routine-you-need-for-strong-and-mobile-hips-and-core-muscles" target="_blank">A yoga instructor says this is the 5-minute yoga routine you need for strong and mobile hips and core muscles</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/workouts/these-7-exercises-improve-joint-range-of-motion-movement-quality-and-overall-mobility-says-a-personal-trainer</link>
                                                                            <description>
                            <![CDATA[ 1Rebel master trainer LJ shares a mobility routine to improve your movement quality as you age. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">fX8C7e4ecysAvzUS3xAhp4</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/Bm2MNnzyv6u3v6ZJGj6NrM-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 29 Oct 2026 06:30:00 +0000</pubDate>                                                                                                                                <updated>Thu, 29 Oct 2026 09:08:59 +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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/Bm2MNnzyv6u3v6ZJGj6NrM-1920-80.jpg">
                                                            <media:credit><![CDATA[Getty Images]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Athletic male in shorts at the gym performing a low squat hold while stretching out his hips]]></media:description>                                                            <media:text><![CDATA[Athletic male in shorts at the gym performing a low squat hold while stretching out his hips]]></media:text>
                                <media:title type="plain"><![CDATA[Athletic male in shorts at the gym performing a low squat hold while stretching out his hips]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/Bm2MNnzyv6u3v6ZJGj6NrM-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>"These five exercises improve joint range of motion, movement quality, and overall mobility," says LJ, a master trainer at London's <a href="https://www.1rebel.com/" target="_blank" rel="nofollow">1Rebel</a>. And as a coach who teaches mobility classes every week, I have to agree they're some of my favorites.</p><p>You only need an exercise mat, nothing else. And while LJ doesn't specify sets, reps, or timings, I provide my recommendations below, plus some of the benefits LJ says you can expect. Check out the video, roll out your mat and get ready to feel loose and free again.</p><p>Here it is!</p><h2 id="watch-master-trainer-39-s-mobility-routine">Watch: Master trainer's 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/DeynHIkTUVz/" target="_blank">A post shared by Tom's Guide Fitness | Workout Tips &amp; Gear (@tomsguidefitness)</a></p><p>A photo posted by </p></blockquote></div><p>As a personal trainer myself, I would recommend programming 45 seconds on and 15 seconds off for 3-5 rounds. If you prefer to work with sets and reps, try 6-8 reps per side per move, and 2 sets of each movement. </p><ul><li><strong>Adductor rocks: </strong>Start on all fours, then extend one leg out to the side, foot flat and toes pointing forward. Keeping your spine neutral, rock your hips back towards your heel, then forward again, moving slowly and under control. <em><strong>Working: </strong></em>Adductors (inner thighs), plus hip mobility in the frontal plane. Great for runners, lifters and anyone who sits a lot. </li><li><strong>Scorpions: </strong>Lie face down with your arms out in a T. Swing one heel up and across your body toward the opposite hand, letting your hips rotate, then return and repeat on the other side.<strong> </strong><em><strong>Working</strong></em><em>: </em>Hip flexors and quads (front-of-hip stretch), spinal rotation and thoracic mobility, and glutes as you control the movement. </li><li><strong>Glute bridge to cross-body overhead reach: </strong>Lie on your back, knees bent, and drive through your heels into a glute bridge. At the top, reach one arm up and across your body overhead, then lower back down with control and alternate sides.<strong> </strong><em><strong>Working: </strong></em>Glutes and hamstrings for hip extension, plus core stability and thoracic rotation, combined with shoulder mobility through the overhead reach.</li><li><strong>Quadruped hip internal rotations: </strong>From all fours, lift one foot slightly off the floor and sweep your foot out to the side so the hip rotates inward, then return. Keep your torso still so the movement comes from the hip. <em><strong>Working</strong></em><em>: </em>Hip internal rotation, an often-neglected range that’s key for running, squatting and change of direction. It also challenges the deep hip rotators. </li><li><strong>Wall clock (shoulder arc): </strong>Stand side-on to a wall and place a forearm or hand against it. Slowly trace an arc with your arm, like moving across the numbers on a clock face, keeping your ribs down and shoulder blade moving smoothly.<strong> </strong><em><strong>Working:</strong></em><em> </em>Shoulder mobility and scapular control, targeting the rotator cuff and the muscles that stabilize the shoulder blade. Particularly useful for overhead work.</li><li><strong>Adductor half-kneeling rock with kettlebell/light weight: </strong>Start in a half-kneeling position with the front leg out to the side. Hold a kettlebell or light weight at your chest as a counterbalance, then rock your hips back and forth, keeping your chest tall. <em><strong>Working:</strong></em><em> </em>Adductor length and hip mobility under light load, plus core and glute engagement to stay stable. </li><li><strong>Prone swimmers:</strong><em> </em>Lie face down with your arms extended overhead and legs straight, forehead hovering just above the mat so your neck stays neutral. Lift your arms and legs slightly off the floor, then alternate opposite arm and leg using a flutter style of small, controlled movement. Keep your glutes engaged and avoid cranking your lower back. <em><strong>Working:</strong></em><em> </em>Spinal extensors (erector spinae) and glutes, plus the mid and lower traps and rear delts for shoulder and posture strength. It’s a great counter to desk-hunched postures.</li></ul><h2 id="what-happened-when-i-tried-it">What happened when I tried it</h2><p>Try to keep the reps similar for each move in each round, and work both sides of the body. If you choose equal-number rounds, you could complete the reps on one side only, then switch to the other side on the next round.</p><div><blockquote><p>I loved this routine, and it helped me feel far looser going into my day or my next workout. </p></blockquote></div><p>Some of these exercises I know already and use with clients; some were actually new to me, such as the glute bridge with overhead reach. I opted for two sets and 6-8 reps per side as a warm-up before coaching a mobility session, and I have since stolen them to use in my next class.</p><p>Combined, these exercises are brilliant for improving the range of motion in your joints and priming the muscles for exercise by increasing blood flow. Repeating these moves over time will improve posture, build range and bolster overall mobility, which means the quality of your movements during workouts should also improve. </p><p>As LJ mentions, you'll internally rotate your hips, strengthen the postural muscles in your back and even target stabilizing muscles like your hip flexors and rotator cuff (the RC includes a group of muscles that stabilize the shoulder joint and sit around the scapulae), which means you're building a body capable of withstanding injury through weakness or underuse/overuse.</p><p>If you're new to mobility or this type of routine, I strongly recommend taking it slowly and stopping if you experience any pain, especially if you have a health condition or injury. </p><p>I loved this routine, and it helped me feel far looser going into my day or my next workout. Let us know if it helps you, too.</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><p>If you suffer from tight hips or back pain, some (or all) of these moves might be useful for you to try, but <strong>stop and rest if you need to. </strong>And if you're unsure <a href="https://www.tomsguide.com/news/this-is-the-most-important-thing-to-do-when-working-your-abs-according-to-a-personal-trainer">how to engage your core properly</a>, this <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">short "bracing" routine</a> might be helpful before you start the routine, just to protect your lower back.</p><p>Move with control, remember to breathe and don't rush your reps. Also remember that training should make you feel good, so focus on what you enjoy about the routine and how it makes your body feel.</p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="vGnNDN" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-to-be-more-mobile-in-their-60s-and-70s-3-low-impact-exercises-you-should-start-with" target="_blank">I teach people to be more mobile in their 60s and 70s: 3 low-impact exercises you should start with</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/forget-burpees-the-pilates-burpee-is-beginner-friendly-and-low-impact-and-youll-love-it" target="_blank">Forget burpees —the 'Pilates burpee' is beginner-friendly and low-impact (and you’ll love it)</a></li><li><a href="https://www.tomsguide.com/wellness/workouts/a-yoga-instructor-says-this-is-the-5-minute-yoga-routine-you-need-for-strong-and-mobile-hips-and-core-muscles" target="_blank">A yoga instructor says this is the 5-minute yoga routine you need for strong and mobile hips and core muscles</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I’ve run 4 marathons in these Lululemon shorts, and they are down to just $29 in this secret deal ]]></title>
                                                                                                <dc:content><![CDATA[ <p>I’ve run seven marathons, so I know what I’m looking for when it comes to finding the perfect pair of shorts. I want enough pockets to carry all my gels, a waistband with a drawcord I can pull tight against my stomach, and legs that don’t ride up or bunch as I move. One pair that I’ve worn for hundreds of miles is the Lululemon Fast and Free High Rise Short, and right now, you can save on most colors and sizes. </p><p>The shorts are currently down to <a href="https://shop.lululemon.com/p/fast-and-free-hr-short-6-inches-5-pocket/g5evibbh9j?color=0001&amp;sz=4" target="_blank">$29 from $78 in Lululemon’s We Made Too Much collection</a>, which runs throughout the year on its website. Grab these while you can, especially if you’ve got a race coming up. </p><div class="product"><a data-dimension112="67363a70-d210-11f1-98d8-337b688c14f9" data-action="Deal Block" data-label="Fast and Free High Rise Short" data-dimension48="Fast and Free High Rise Short" data-dimension25="$29" href="https://shop.lululemon.com/p/fast-and-free-hr-short-6-inches-5-pocket/g5evibbh9j?color=0001&amp;sz=4" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="hPNeSzPxCXSjxaqvSaRoE8" name="LW7CPPS_0001_1 copy" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hPNeSzPxCXSjxaqvSaRoE8-1920-80.jpg" mos="" align="middle" fullscreen="" width="1800" height="1800" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/fast-and-free-hr-short-6-inches-5-pocket/g5evibbh9j?color=0001&amp;sz=4" target="_blank" rel="nofollow" data-dimension112="67363a70-d210-11f1-98d8-337b688c14f9" data-action="Deal Block" data-label="Fast and Free High Rise Short" data-dimension48="Fast and Free High Rise Short" data-dimension25="$29">Fast and Free High Rise Short: was $78 now $29</a></strong><br />The shorts are on sale in several different colors. The biggest saving I could find was on the black colorway (which rarely happens), but find the best deal for you by looking through all the different options in your size. <a class="view-deal button" href="https://shop.lululemon.com/p/fast-and-free-hr-short-6-inches-5-pocket/g5evibbh9j?color=0001&amp;sz=4" target="_blank" rel="nofollow" data-dimension112="67363a70-d210-11f1-98d8-337b688c14f9" data-action="Deal Block" data-label="Fast and Free High Rise Short" data-dimension48="Fast and Free High Rise Short" data-dimension25="$29">View Deal</a></p></div><p>When I say these are the perfect running shorts, I’m not exaggerating. In fact, the only downside to the Fast and Free shorts is that they come with a hefty price tag, but for $29, I’m stocking up while I can. </p><p>These shorts are buttery soft against the skin, while still being extremely sweat-wicking. I wore them for my most recent marathon in Frankfurt, and despite awful conditions and being soaked on the start line, I didn’t experience any rubbing or chafing. </p><p>There are also five different pockets to choose from — two drop-in pockets on the legs big enough for a smartphone and several gels, as well as a large drop-in pocket on the waistband that easily fits my iPhone 18 Pro, allowing me to leave my running belt at home. There are also two smaller waistband pockets for your keys and other essentials. </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/De_qjpngAQI/" target="_blank">A post shared by Jane McGuire (@janecmcguire)</a></p><p>A photo posted by </p></blockquote></div><p>These shorts feel weightless and allow you to move unrestricted as you pick up the pace. I’ve never had an issue with the legs riding up, and they come in a longer 8-inch leg length for those who want the extra coverage. </p><p>Grab them while you can: they won’t be this price for long! </p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/running/ive-run-4-marathons-in-these-lululemon-shorts-and-they-are-down-to-just-usd29-in-this-secret-deal</link>
                                                                            <description>
                            <![CDATA[ Grab these Lululemon running shorts while you still can. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">mcunWT3aYww6TA8WMLzoNL</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/iuPPVZVmRixD4PFKFyj5vY-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 29 Oct 2026 04:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Running]]></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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/iuPPVZVmRixD4PFKFyj5vY-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Jane McGuire]]></media:description>                                                            <media:text><![CDATA[Jane McGuire]]></media:text>
                                <media:title type="plain"><![CDATA[Jane McGuire]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/iuPPVZVmRixD4PFKFyj5vY-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I’ve run seven marathons, so I know what I’m looking for when it comes to finding the perfect pair of shorts. I want enough pockets to carry all my gels, a waistband with a drawcord I can pull tight against my stomach, and legs that don’t ride up or bunch as I move. One pair that I’ve worn for hundreds of miles is the Lululemon Fast and Free High Rise Short, and right now, you can save on most colors and sizes. </p><p>The shorts are currently down to <a href="https://shop.lululemon.com/p/fast-and-free-hr-short-6-inches-5-pocket/g5evibbh9j?color=0001&amp;sz=4" target="_blank">$29 from $78 in Lululemon’s We Made Too Much collection</a>, which runs throughout the year on its website. Grab these while you can, especially if you’ve got a race coming up. </p><div class="product"><a data-dimension112="67363a70-d210-11f1-98d8-337b688c14f9" data-action="Deal Block" data-label="Fast and Free High Rise Short" data-dimension48="Fast and Free High Rise Short" data-dimension25="$29" href="https://shop.lululemon.com/p/fast-and-free-hr-short-6-inches-5-pocket/g5evibbh9j?color=0001&amp;sz=4" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="hPNeSzPxCXSjxaqvSaRoE8" name="LW7CPPS_0001_1 copy" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hPNeSzPxCXSjxaqvSaRoE8-1920-80.jpg" mos="" align="middle" fullscreen="" width="1800" height="1800" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/fast-and-free-hr-short-6-inches-5-pocket/g5evibbh9j?color=0001&amp;sz=4" target="_blank" rel="nofollow" data-dimension112="67363a70-d210-11f1-98d8-337b688c14f9" data-action="Deal Block" data-label="Fast and Free High Rise Short" data-dimension48="Fast and Free High Rise Short" data-dimension25="$29">Fast and Free High Rise Short: was $78 now $29</a></strong><br />The shorts are on sale in several different colors. The biggest saving I could find was on the black colorway (which rarely happens), but find the best deal for you by looking through all the different options in your size. <a class="view-deal button" href="https://shop.lululemon.com/p/fast-and-free-hr-short-6-inches-5-pocket/g5evibbh9j?color=0001&amp;sz=4" target="_blank" rel="nofollow" data-dimension112="67363a70-d210-11f1-98d8-337b688c14f9" data-action="Deal Block" data-label="Fast and Free High Rise Short" data-dimension48="Fast and Free High Rise Short" data-dimension25="$29">View Deal</a></p></div><p>When I say these are the perfect running shorts, I’m not exaggerating. In fact, the only downside to the Fast and Free shorts is that they come with a hefty price tag, but for $29, I’m stocking up while I can. </p><p>These shorts are buttery soft against the skin, while still being extremely sweat-wicking. I wore them for my most recent marathon in Frankfurt, and despite awful conditions and being soaked on the start line, I didn’t experience any rubbing or chafing. </p><p>There are also five different pockets to choose from — two drop-in pockets on the legs big enough for a smartphone and several gels, as well as a large drop-in pocket on the waistband that easily fits my iPhone 18 Pro, allowing me to leave my running belt at home. There are also two smaller waistband pockets for your keys and other essentials. </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/De_qjpngAQI/" target="_blank">A post shared by Jane McGuire (@janecmcguire)</a></p><p>A photo posted by </p></blockquote></div><p>These shorts feel weightless and allow you to move unrestricted as you pick up the pace. I’ve never had an issue with the legs riding up, and they come in a longer 8-inch leg length for those who want the extra coverage. </p><p>Grab them while you can: they won’t be this price for long! </p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 25 best fall running shoe deals: Get up to 50% off New Balance, Nike and Hoka ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Want to stay active through the fall season? A bunch of brands are offering <a href="https://www.amazon.com/Womens-Running-Shoes/b/ref=dp_bc_5?ie=UTF8&amp;node=679360011" target="_blank" rel="nofollow">fall running shoe deals, including Asics, New Balance, Brooks and more</a>.</p><p>I've searched everywhere to find the biggest discounts on the most popular shoes, so I've done all the hard work for you. Keep scrolling to check out the best running shoe deals! Whether you're looking for a comfortable max cushioned pair or want a lightweight shoe to set PRs in, there's something for everybody.</p><p><strong>Note: </strong>prices vary depending on the size and color you choose; search the different color options available in your size to find the best deals.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links </span></h3><ul><li><strong>New Balance: </strong><a href="https://www.amazon.com/stores/page/855D4CDF-ADB7-4BE8-9E26-A085D029E4B5?" target="_blank" rel="nofollow"><strong>up to 50% off</strong></a></li><li><strong>Asics: </strong><a href="https://www.amazon.com/stores/page/848769B1-4C68-4CA5-B2E7-A4480A3FBF59" target="_blank" rel="nofollow"><strong>deals from $54</strong></a></li><li><strong>Adidas: </strong><a href="https://www.amazon.com/stores/adidas/page/5E398A61-45C7-46F9-A6C6-5B4797CC5063?" target="_blank" rel="nofollow"><strong>deals from $39</strong></a></li><li><strong>Brooks: </strong><a href="https://www.amazon.com/stores/Brooks/page/B6834DFA-396F-4E38-98F6-3D2739393271?" target="_blank" rel="nofollow"><strong>up to 40% off</strong></a></li><li><strong>Hoka: </strong><a href="https://www.hoka.com/en/us/sale/" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li><li><strong>Nike: </strong><a href="https://www.amazon.com/stores/page/E9C7C6A6-9A88-4959-A67F-4D44FC67320F" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li></ul><h3 class="article-body__section" id="section-best-new-balance-deals"><span>Best New Balance Deals</span></h3><div class="product"><a data-dimension112="c2df5748-d2c0-11f1-abac-87b33ee2717a" data-action="Deal Block" data-label="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension48="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension25="$108" href="https://www.amazon.com/New-Balance-FuelCell-Running-Afterglow/dp/B0F4LLKZCH" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:880px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="zMXtGm9YKG3arrNYXpTBH" name="New Balance Rebel v5 sq" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zMXtGm9YKG3arrNYXpTBH-1920-80.jpg" mos="" align="middle" fullscreen="" width="880" height="880" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-FuelCell-Running-Afterglow/dp/B0F4LLKZCH" target="_blank" rel="nofollow" data-dimension112="c2df5748-d2c0-11f1-abac-87b33ee2717a" data-action="Deal Block" data-label="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension48="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension25="$108">FuelCell Rebel v5 Running Shoes (Women's): was $144 now $108</a></strong><br />The lightweight <a href="https://www.tomsguide.com/wellness/running/new-balance-rebel-v5-review">New Balance FuelCell Rebel v5</a> is a comfortable and speedy daily trainer that's perfect for those who don't love the feel of max-cushioned shoes, as it has a more grounded feel.<a class="view-deal button" href="https://www.amazon.com/New-Balance-FuelCell-Running-Afterglow/dp/B0F4LLKZCH" target="_blank" rel="nofollow" data-dimension112="c2df5748-d2c0-11f1-abac-87b33ee2717a" data-action="Deal Block" data-label="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension48="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension25="$108">View Deal</a></p></div><div class="product"><a data-dimension112="c2df57ac-d2c0-11f1-9922-b5bc8ba20a25" data-action="Deal Block" data-label="Fresh Foam X Hierro v9 (Women's)" data-dimension48="Fresh Foam X Hierro v9 (Women's)" data-dimension25="$123" href="https://www.amazon.com/New-Balance-Womens-Running-Afterglow/dp/B0F4LHFJZH" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:825px;"><p class="vanilla-image-block" style="padding-top:60.00%;"><img id="rKNw53FMMtAELn6kVTTGxk" name="New Balance Fresh Foam X Hierro v9" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/rKNw53FMMtAELn6kVTTGxk-1920-80.png" mos="" align="middle" fullscreen="" width="825" height="495" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-Womens-Running-Afterglow/dp/B0F4LHFJZH" target="_blank" rel="nofollow" data-dimension112="c2df57ac-d2c0-11f1-9922-b5bc8ba20a25" data-action="Deal Block" data-label="Fresh Foam X Hierro v9 (Women's)" data-dimension48="Fresh Foam X Hierro v9 (Women's)" data-dimension25="$123">Fresh Foam X Hierro v9 (Women's): was $159 now $123</a></strong><br />The <a href="https://www.tomsguide.com/wellness/running/new-balance-fresh-foam-x-hierro-v9-review">New Balance Fresh Foam X Hierro v9</a> is a comfortable trail-running and hiking shoe that’s great for active trips. Despite its plush feel, it's still nice and stable with solid grip. You probably won't set your fastest times in this shoe, but it feels great to run in.<a class="view-deal button" href="https://www.amazon.com/New-Balance-Womens-Running-Afterglow/dp/B0F4LHFJZH" target="_blank" rel="nofollow" data-dimension112="c2df57ac-d2c0-11f1-9922-b5bc8ba20a25" data-action="Deal Block" data-label="Fresh Foam X Hierro v9 (Women's)" data-dimension48="Fresh Foam X Hierro v9 (Women's)" data-dimension25="$123">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5810-d2c0-11f1-b235-7d0176f3f2d7" data-action="Deal Block" data-label="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension48="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension25="$144" href="https://www.amazon.com/New-Balance-Running-Metallic-Inkwell/dp/B0CLB6X87W" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:880px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="XwbzzRSwcghwdApXRMQfb5" name="New Balance 1080v14 sq" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XwbzzRSwcghwdApXRMQfb5-1920-80.jpg" mos="" align="middle" fullscreen="" width="880" height="880" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-Running-Metallic-Inkwell/dp/B0CLB6X87W" target="_blank" rel="nofollow" data-dimension112="c2df5810-d2c0-11f1-b235-7d0176f3f2d7" data-action="Deal Block" data-label="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension48="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension25="$144">Fresh Foam X 1080v14 Running Shoe (Men's): was $164 now $144</a></strong><br />We gave this shoe a 4-star rating in our <a href="https://www.tomsguide.com/wellness/running/new-balance-fresh-foam-x-1080v14-review">New Balance Fresh Foam X 1080v14 review</a>, saying that this is a cushioned daily trainer that offers a great balance of comfort and weight.<a class="view-deal button" href="https://www.amazon.com/New-Balance-Running-Metallic-Inkwell/dp/B0CLB6X87W" target="_blank" rel="nofollow" data-dimension112="c2df5810-d2c0-11f1-b235-7d0176f3f2d7" data-action="Deal Block" data-label="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension48="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension25="$144">View Deal</a></p></div><div class="product"><a data-dimension112="c2df58a6-d2c0-11f1-ae3f-e5f6a5a0b16d" data-action="Deal Block" data-label="FuelCell Supercomp Elite V5 (Women's)" data-dimension48="FuelCell Supercomp Elite V5 (Women's)" data-dimension25="$145" href="https://www.amazon.com/New-Balance-FuelCell-SuperComp-Tangerine/dp/B0F4LZ7VDR" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1267px;"><p class="vanilla-image-block" style="padding-top:54.85%;"><img id="BXfy6JhfauCEwEyTDyxFe3" name="FuelCell Supercomp Elite V5 (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/BXfy6JhfauCEwEyTDyxFe3-1920-80.jpg" mos="" align="middle" fullscreen="" width="1267" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-FuelCell-SuperComp-Tangerine/dp/B0F4LZ7VDR" target="_blank" rel="nofollow" data-dimension112="c2df58a6-d2c0-11f1-ae3f-e5f6a5a0b16d" data-action="Deal Block" data-label="FuelCell Supercomp Elite V5 (Women's)" data-dimension48="FuelCell Supercomp Elite V5 (Women's)" data-dimension25="$145">FuelCell Supercomp Elite V5 (Women's): was $264 now $145</a></strong><br />Our Fitness Editor, Jane McGuire, ran her fastest marathon in the Supercomp Elite V5 — and our Senior Fitness Writer, Nick Harris-Fry loved their lightweight, propulsive design in his <a href="https://www.tomsguide.com/wellness/running/new-balance-sc-elite-v5-review">New Balance FuelCell Supercomp Elite V5 review</a>. Don't sleep on this saving!<a class="view-deal button" href="https://www.amazon.com/New-Balance-FuelCell-SuperComp-Tangerine/dp/B0F4LZ7VDR" target="_blank" rel="nofollow" data-dimension112="c2df58a6-d2c0-11f1-ae3f-e5f6a5a0b16d" data-action="Deal Block" data-label="FuelCell Supercomp Elite V5 (Women's)" data-dimension48="FuelCell Supercomp Elite V5 (Women's)" data-dimension25="$145">View Deal</a></p></div><h3 class="article-body__section" id="section-best-asics-deals"><span>Best Asics Deals</span></h3><div class="product"><a data-dimension112="c2df59a0-d2c0-11f1-9c7c-dbde66422e87" data-action="Deal Block" data-label="Gel-Pulse 16 (Women's)" data-dimension48="Gel-Pulse 16 (Women's)" data-dimension25="$47" href="https://www.amazon.com/ASICS-Womens-Gel-Pulse-Running-Midnight/dp/B0F63XHPW5" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:48.88%;"><img id="Woj2dkTQp2a9nuWs5nFuDg" name="Gel-Pulse 16 (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Woj2dkTQp2a9nuWs5nFuDg-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="565" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Pulse-Running-Midnight/dp/B0F63XHPW5" target="_blank" rel="nofollow" data-dimension112="c2df59a0-d2c0-11f1-9c7c-dbde66422e87" data-action="Deal Block" data-label="Gel-Pulse 16 (Women's)" data-dimension48="Gel-Pulse 16 (Women's)" data-dimension25="$47">Gel-Pulse 16 (Women's): was $100 now $47</a></strong><br />This is one of the cheapest Asics running shoe deals you'll find, so this shoe is definitely worth a purchase. However, stock is limited, so act fast! It's regarded as a comfy and versatile sneaker that suits neutral runners in particular.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Gel-Pulse-Running-Midnight/dp/B0F63XHPW5" target="_blank" rel="nofollow" data-dimension112="c2df59a0-d2c0-11f1-9c7c-dbde66422e87" data-action="Deal Block" data-label="Gel-Pulse 16 (Women's)" data-dimension48="Gel-Pulse 16 (Women's)" data-dimension25="$47">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5a0e-d2c0-11f1-bdc9-95741a9ee26f" data-action="Deal Block" data-label="Gel-Kayano 30 (Women's)" data-dimension48="Gel-Kayano 30 (Women's)" data-dimension25="$69" href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1160px;"><p class="vanilla-image-block" style="padding-top:46.29%;"><img id="iHsvdtLnzyeWEyCZV8HBYe" name="Gel-Kayano 30 (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/iHsvdtLnzyeWEyCZV8HBYe-1920-80.jpg" mos="" align="middle" fullscreen="" width="1160" height="537" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow" data-dimension112="c2df5a0e-d2c0-11f1-bdc9-95741a9ee26f" data-action="Deal Block" data-label="Gel-Kayano 30 (Women's)" data-dimension48="Gel-Kayano 30 (Women's)" data-dimension25="$69">Gel-Kayano 30 (Women's): was $160 now $69</a></strong><br />The Gel Kayano 30 running shoes are an older model, but they're amazingly cheap with 56% off. They're designed to provide advanced stability and soft cushioning for neutral runners and overpronators alike. Our Deals Editor-in-Chief, Louis Ramirez, wrote: "I've been using these shoes for almost two years now. (I loved them so much I bought a second pair months after buying my first pair). I find that they're great for casual runs on the treadmill, HIIT sessions, and long distance running outdoors."<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow" data-dimension112="c2df5a0e-d2c0-11f1-bdc9-95741a9ee26f" data-action="Deal Block" data-label="Gel-Kayano 30 (Women's)" data-dimension48="Gel-Kayano 30 (Women's)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5a72-d2c0-11f1-94eb-63c8e0f41529" data-action="Deal Block" data-label="Women's Novablast 4" data-dimension48="Women's Novablast 4" data-dimension25="$67" href="https://www.amazon.com/ASICS-Womens-NOVABLAST-Running-Expanse/dp/B0CFP3J6RB" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1200px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="wMYSVC2325TPeXMt7TJ9t3" name="Asics Novablast 4" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/wMYSVC2325TPeXMt7TJ9t3-1920-80.jpg" mos="" align="middle" fullscreen="" width="1200" height="1200" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-NOVABLAST-Running-Expanse/dp/B0CFP3J6RB" target="_blank" rel="nofollow" data-dimension112="c2df5a72-d2c0-11f1-94eb-63c8e0f41529" data-action="Deal Block" data-label="Women's Novablast 4" data-dimension48="Women's Novablast 4" data-dimension25="$67">Women's Novablast 4: was $140 now $67</a></strong><br />Old but gold. While the Novablast 6 is now available, the Novablast 4 is beloved by the Tom's Guide team — especially our Fitness Editor Jane McGuire, who wrote: "I've run over 100 miles in this shoe, and it's still one I reach for when I'm heading out for a long run."<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-NOVABLAST-Running-Expanse/dp/B0CFP3J6RB" target="_blank" rel="nofollow" data-dimension112="c2df5a72-d2c0-11f1-94eb-63c8e0f41529" data-action="Deal Block" data-label="Women's Novablast 4" data-dimension48="Women's Novablast 4" data-dimension25="$67">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5acc-d2c0-11f1-9c7a-17ad5fda44b4" data-action="Deal Block" data-label="Sonicblast Road Running Shoes (Men's)" data-dimension48="Sonicblast Road Running Shoes (Men's)" data-dimension25="$81" href="https://www.amazon.com/Asics-SONICBLAST-Running-Winter-Stillwater/dp/B0DPLQ32YV" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1528px;"><p class="vanilla-image-block" style="padding-top:75.00%;"><img id="rD9sdYvxaqtEV2BgyMfTx" name="Sonicblast" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/rD9sdYvxaqtEV2BgyMfTx-1920-80.jpg" mos="" align="middle" fullscreen="" width="1528" height="1146" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Asics-SONICBLAST-Running-Winter-Stillwater/dp/B0DPLQ32YV" target="_blank" rel="nofollow" data-dimension112="c2df5acc-d2c0-11f1-9c7a-17ad5fda44b4" data-action="Deal Block" data-label="Sonicblast Road Running Shoes (Men's)" data-dimension48="Sonicblast Road Running Shoes (Men's)" data-dimension25="$81">Sonicblast Road Running Shoes (Men's): was $180 now $81</a></strong><br />Suited for both fast runs and everyday training, the Asics Sonicblast are super lightweight and propulsive. There's an Astroplate mechanism to help you shoot forward, as well as FF Blast Max and FF Turbo cushioning for a bouncy feel underfoot.<a class="view-deal button" href="https://www.amazon.com/Asics-SONICBLAST-Running-Winter-Stillwater/dp/B0DPLQ32YV" target="_blank" rel="nofollow" data-dimension112="c2df5acc-d2c0-11f1-9c7a-17ad5fda44b4" data-action="Deal Block" data-label="Sonicblast Road Running Shoes (Men's)" data-dimension48="Sonicblast Road Running Shoes (Men's)" data-dimension25="$81">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5b30-d2c0-11f1-9150-d3d7297169c5" data-action="Deal Block" data-label="Novablast 5 (Men's)" data-dimension48="Novablast 5 (Men's)" data-dimension25="$129" href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1166px;"><p class="vanilla-image-block" style="padding-top:48.80%;"><img id="4pk4xESon4iEcQDmd7TqZF" name="Novablast 5 (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4pk4xESon4iEcQDmd7TqZF-1920-80.jpg" mos="" align="middle" fullscreen="" width="1166" height="569" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow" data-dimension112="c2df5b30-d2c0-11f1-9150-d3d7297169c5" data-action="Deal Block" data-label="Novablast 5 (Men's)" data-dimension48="Novablast 5 (Men's)" data-dimension25="$129">Novablast 5 (Men's): was $160 now $129</a></strong><br />We voted the Asics Novablast 6 as the <a href="https://www.tomsguide.com/best-picks/best-running-shoes">best running shoes</a> you can buy right now, but before that, the <a href="https://www.tomsguide.com/wellness/running/asics-novablast-5-review">Asics Novablast 5</a> had the top spot. They quickly stood out for their balance of comfort, support and fun, making them a pair of shoes you will actually look forward to running in. They're lightweight, durable and have a soft, springy feel underfoot that helps absorb impact while keeping runs enjoyable.<a class="view-deal button" href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow" data-dimension112="c2df5b30-d2c0-11f1-9150-d3d7297169c5" data-action="Deal Block" data-label="Novablast 5 (Men's)" data-dimension48="Novablast 5 (Men's)" data-dimension25="$129">View Deal</a></p></div><h3 class="article-body__section" id="section-best-nike-deals"><span>Best Nike Deals</span></h3><div class="product"><a data-dimension112="c2df5bee-d2c0-11f1-aff0-45b8bc229328" data-action="Deal Block" data-label="Pegasus 42 (Men's)" data-dimension48="Pegasus 42 (Men's)" data-dimension25="$82" href="https://www.nike.com/t/pegasus-42-mens-road-running-shoes-S1bYkOza/IB1873-107" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1070px;"><p class="vanilla-image-block" style="padding-top:125.05%;"><img id="uxG2rhW9L4NBaWbeVEreNS" name="Nike Pegasus 42" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/uxG2rhW9L4NBaWbeVEreNS-1920-80.png" mos="" align="middle" fullscreen="" width="1070" height="1338" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nike.com/t/pegasus-42-mens-road-running-shoes-S1bYkOza/IB1873-107" target="_blank" rel="nofollow" data-dimension112="c2df5bee-d2c0-11f1-aff0-45b8bc229328" data-action="Deal Block" data-label="Pegasus 42 (Men's)" data-dimension48="Pegasus 42 (Men's)" data-dimension25="$82">Pegasus 42 (Men's): was $145 now $82</a></strong><br />Earning a 3.5-star rating in our <a href="https://www.tomsguide.com/wellness/running/nike-pegasus-42-review">Nike Pegasus 42 review</a>, we currently rank this as one of the <a href="https://www.tomsguide.com/best-picks/best-running-shoes">best running shoes</a> you can buy in terms of value. Compared to the Pegasus 41 (which was already great,) the 42 feels even smoother and more energetic underfoot. It's a great shoe for just about anybody.<a class="view-deal button" href="https://www.nike.com/t/pegasus-42-mens-road-running-shoes-S1bYkOza/IB1873-107" target="_blank" rel="nofollow" data-dimension112="c2df5bee-d2c0-11f1-aff0-45b8bc229328" data-action="Deal Block" data-label="Pegasus 42 (Men's)" data-dimension48="Pegasus 42 (Men's)" data-dimension25="$82">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5c52-d2c0-11f1-a82a-ad821506e16a" data-action="Deal Block" data-label="Vomero 18 Running Shoes (Women's)" data-dimension48="Vomero 18 Running Shoes (Women's)" data-dimension25="$116" href="https://www.amazon.com/dp/B0FRNJB2NY" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:44.46%;"><img id="on8DUvsokY6RbJszwfXseQ" name="Vomero" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/on8DUvsokY6RbJszwfXseQ-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="309" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0FRNJB2NY" target="_blank" rel="nofollow" data-dimension112="c2df5c52-d2c0-11f1-a82a-ad821506e16a" data-action="Deal Block" data-label="Vomero 18 Running Shoes (Women's)" data-dimension48="Vomero 18 Running Shoes (Women's)" data-dimension25="$116">Vomero 18 Running Shoes (Women's): was $155 now $116</a></strong><br />The <a href="https://www.tomsguide.com/wellness/running/nike-vomero-18-review">Nike Vomero 18</a> is a max-cushioned cruiser that's ideal for protecting the body on long and easy runs. It's plush, comfortable and stable. The shoe is pretty heavy, but if you're looking for plush, sink-in comfort, this one ticks that box. <a class="view-deal button" href="https://www.amazon.com/dp/B0FRNJB2NY" target="_blank" rel="nofollow" data-dimension112="c2df5c52-d2c0-11f1-a82a-ad821506e16a" data-action="Deal Block" data-label="Vomero 18 Running Shoes (Women's)" data-dimension48="Vomero 18 Running Shoes (Women's)" data-dimension25="$116">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5cb6-d2c0-11f1-9f82-455a1192f058" data-action="Deal Block" data-label="Vomero Plus (Men's)" data-dimension48="Vomero Plus (Men's)" data-dimension25="$152" href="https://www.nike.com/t/vomero-plus-mens-road-running-shoes-5npsVBwT/HV8150-111" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1070px;"><p class="vanilla-image-block" style="padding-top:125.05%;"><img id="ee4dBpGa8AkgSBMVwAnYhb" name="Vomero Plus (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ee4dBpGa8AkgSBMVwAnYhb-1920-80.jpg" mos="" align="middle" fullscreen="" width="1070" height="1338" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nike.com/t/vomero-plus-mens-road-running-shoes-5npsVBwT/HV8150-111" target="_blank" rel="nofollow" data-dimension112="c2df5cb6-d2c0-11f1-9f82-455a1192f058" data-action="Deal Block" data-label="Vomero Plus (Men's)" data-dimension48="Vomero Plus (Men's)" data-dimension25="$152">Vomero Plus (Men's): was $180 now $152</a></strong><br />The <a href="https://www.tomsguide.com/wellness/running/i-ran-50-miles-in-the-nike-vomero-plus-and-its-my-new-favorite-running-shoe">Nike Vomero Plus</a> offers an unrivalled level of bounce and fun thanks to its springy ZoomX midsole. It makes easy and long runs all the more enjoyable in particular. The biggest drawback is the fact it costs $180 at full price, but that’s no longer a problem because the Vomero Plus is reduced right now.<a class="view-deal button" href="https://www.nike.com/t/vomero-plus-mens-road-running-shoes-5npsVBwT/HV8150-111" target="_blank" rel="nofollow" data-dimension112="c2df5cb6-d2c0-11f1-9f82-455a1192f058" data-action="Deal Block" data-label="Vomero Plus (Men's)" data-dimension48="Vomero Plus (Men's)" data-dimension25="$152">View Deal</a></p></div><h3 class="article-body__section" id="section-best-hoka-deals"><span>Best Hoka Deals</span></h3><div class="product"><a data-dimension112="c2df5d74-d2c0-11f1-8d42-c9caeb93b15c" data-action="Deal Block" data-label="Arahi 8 (Women's)" data-dimension48="Arahi 8 (Women's)" data-dimension25="$120" href="https://www.hoka.com/en/us/womens-everyday-running-shoes/arahi-8/1168691.html?dwvar_1168691_color=FSTS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1932px;"><p class="vanilla-image-block" style="padding-top:81.11%;"><img id="EUf3iisgBNqSoAfRcsnYMU" name="Arahi 8" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/EUf3iisgBNqSoAfRcsnYMU-1920-80.jpg" mos="" align="middle" fullscreen="" width="1932" height="1567" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/womens-everyday-running-shoes/arahi-8/1168691.html?dwvar_1168691_color=FSTS" target="_blank" rel="nofollow" data-dimension112="c2df5d74-d2c0-11f1-8d42-c9caeb93b15c" data-action="Deal Block" data-label="Arahi 8 (Women's)" data-dimension48="Arahi 8 (Women's)" data-dimension25="$120">Arahi 8 (Women's): was $150 now $120</a></strong><br />The Arahi 8 is the stable counterpart to the Clifton 10, offering extra support for runners who overpronate along with Hoka's familiar smooth, cushioned ride. It'd great for neutral runners, and the newer Arahi 9 is very similar in all respects, so the older model is definitely better value in the sale.<a class="view-deal button" href="https://www.hoka.com/en/us/womens-everyday-running-shoes/arahi-8/1168691.html?dwvar_1168691_color=FSTS" target="_blank" rel="nofollow" data-dimension112="c2df5d74-d2c0-11f1-8d42-c9caeb93b15c" data-action="Deal Block" data-label="Arahi 8 (Women's)" data-dimension48="Arahi 8 (Women's)" data-dimension25="$120">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5dd8-d2c0-11f1-9f4e-1192ecbad4b4" data-action="Deal Block" data-label="Clifton 10 (Men's)" data-dimension48="Clifton 10 (Men's)" data-dimension25="$124" href="https://www.hoka.com/en/us/mens-everyday-running-gear/clifton-10/1162030.html?dwvar_1162030_color=WKY" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1932px;"><p class="vanilla-image-block" style="padding-top:81.11%;"><img id="pTkmatx4tcURfCFTcWdCu9" name="Clifton 10" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pTkmatx4tcURfCFTcWdCu9-1920-80.jpg" mos="" align="middle" fullscreen="" width="1932" height="1567" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/mens-everyday-running-gear/clifton-10/1162030.html?dwvar_1162030_color=WKY" target="_blank" rel="nofollow" data-dimension112="c2df5dd8-d2c0-11f1-9f4e-1192ecbad4b4" data-action="Deal Block" data-label="Clifton 10 (Men's)" data-dimension48="Clifton 10 (Men's)" data-dimension25="$124">Clifton 10 (Men's): was $155 now $124</a></strong><br />The Clifton is the most popular Hoka running shoe for a reason. It’s the perfect place to start with the brand, offering a smooth, comfortable ride that will suit runners of all levels well. It also offers better value than Hoka's rivals, like the Bondi 9.<a class="view-deal button" href="https://www.hoka.com/en/us/mens-everyday-running-gear/clifton-10/1162030.html?dwvar_1162030_color=WKY" target="_blank" rel="nofollow" data-dimension112="c2df5dd8-d2c0-11f1-9f4e-1192ecbad4b4" data-action="Deal Block" data-label="Clifton 10 (Men's)" data-dimension48="Clifton 10 (Men's)" data-dimension25="$124">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5e32-d2c0-11f1-ab60-7707c7d9918d" data-action="Deal Block" data-label="Clifton 9 GTX (Women's)" data-dimension48="Clifton 9 GTX (Women's)" data-dimension25="$132" href="https://www.hoka.com/en/us/womens-everyday-running-shoes/clifton-9-gtx/1141490.html?dwvar_1141490_color=BNDR" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1932px;"><p class="vanilla-image-block" style="padding-top:81.11%;"><img id="RRxC8fKVUmNBdxEfjnVQFf" name="Clifton 9 GTX (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/RRxC8fKVUmNBdxEfjnVQFf-1920-80.webp" mos="" align="middle" fullscreen="" width="1932" height="1567" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/womens-everyday-running-shoes/clifton-9-gtx/1141490.html?dwvar_1141490_color=BNDR" target="_blank" rel="nofollow" data-dimension112="c2df5e32-d2c0-11f1-ab60-7707c7d9918d" data-action="Deal Block" data-label="Clifton 9 GTX (Women's)" data-dimension48="Clifton 9 GTX (Women's)" data-dimension25="$132">Clifton 9 GTX (Women's): was $165 now $132</a></strong><br />The <a href="https://www.tomsguide.com/reviews/hoka-clifton-9">Hoka Clifton 9</a> is a cushioned, everyday running shoe that’ll work well for beginners and more experienced runners alike. It’s not the fanciest or the fastest shoe around, but it’s reliably comfortable, whether you’re training for a marathon or using this shoe for your walking workouts. The GTX version adds weatherproofing, so you'll get more out of your walks and runs, rain or shine.<a class="view-deal button" href="https://www.hoka.com/en/us/womens-everyday-running-shoes/clifton-9-gtx/1141490.html?dwvar_1141490_color=BNDR" target="_blank" rel="nofollow" data-dimension112="c2df5e32-d2c0-11f1-ab60-7707c7d9918d" data-action="Deal Block" data-label="Clifton 9 GTX (Women's)" data-dimension48="Clifton 9 GTX (Women's)" data-dimension25="$132">View Deal</a></p></div><h3 class="article-body__section" id="section-best-brooks-deals"><span>Best Brooks Deals</span></h3><div class="product"><a data-dimension112="c2df5ef0-d2c0-11f1-9329-334fc9bf762d" data-action="Deal Block" data-label="Hyperion" data-dimension48="Hyperion" data-dimension25="$72" href="https://www.amazon.com/Brooks-Mens-Hyperion-Neutral-Running/dp/B0BMT316TB?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1035px;"><p class="vanilla-image-block" style="padding-top:67.15%;"><img id="crYpUdxjpNUYpBCknBJzHX" name="Brooks Hyperion" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/crYpUdxjpNUYpBCknBJzHX-1920-80.jpg" mos="" align="middle" fullscreen="" width="1035" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Brooks-Mens-Hyperion-Neutral-Running/dp/B0BMT316TB?" target="_blank" rel="nofollow" data-dimension112="c2df5ef0-d2c0-11f1-9329-334fc9bf762d" data-action="Deal Block" data-label="Hyperion" data-dimension48="Hyperion" data-dimension25="$72">Hyperion: was $140 now $72</a></strong><br />With prices starting from $72, this is one of the more affordable Brooks shoes you'll find. They're designed to be lightweight, speedy and to help you navigate transitions with ease.<a class="view-deal button" href="https://www.amazon.com/Brooks-Mens-Hyperion-Neutral-Running/dp/B0BMT316TB?" target="_blank" rel="nofollow" data-dimension112="c2df5ef0-d2c0-11f1-9329-334fc9bf762d" data-action="Deal Block" data-label="Hyperion" data-dimension48="Hyperion" data-dimension25="$72">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5f54-d2c0-11f1-aeb0-e710137431e9" data-action="Deal Block" data-label="Hyperion Max 3 (Men's)" data-dimension48="Hyperion Max 3 (Men's)" data-dimension25="$108" href="https://www.amazon.com/dp/B0DM3MTXGK?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:840px;"><p class="vanilla-image-block" style="padding-top:68.45%;"><img id="bf7gzstL3kTG3roVNuaN4L" name="Brooks Hyperion Max" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bf7gzstL3kTG3roVNuaN4L-1920-80.png" mos="" align="middle" fullscreen="" width="840" height="575" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0DM3MTXGK?" target="_blank" rel="nofollow" data-dimension112="c2df5f54-d2c0-11f1-aeb0-e710137431e9" data-action="Deal Block" data-label="Hyperion Max 3 (Men's)" data-dimension48="Hyperion Max 3 (Men's)" data-dimension25="$108">Hyperion Max 3 (Men's): was $199 now $108</a></strong><br />The Brooks Hyperion Max 3 is a plated training shoe with a mega-stack of cushioning in its midsole, the top layer of which is made from a particularly springy PEBA material. It's a speedier option than shoes like the Glycerin and Ghost, and still comfortable for easy runs as well.<a class="view-deal button" href="https://www.amazon.com/dp/B0DM3MTXGK?" target="_blank" rel="nofollow" data-dimension112="c2df5f54-d2c0-11f1-aeb0-e710137431e9" data-action="Deal Block" data-label="Hyperion Max 3 (Men's)" data-dimension48="Hyperion Max 3 (Men's)" data-dimension25="$108">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5fcc-d2c0-11f1-9639-7d5af08a33f8" data-action="Deal Block" data-label="Ghost Max 3 (Men's)" data-dimension48="Ghost Max 3 (Men's)" data-dimension25="$109" href="https://www.amazon.com/dp/B0DM3R7VD1?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:890px;"><p class="vanilla-image-block" style="padding-top:64.61%;"><img id="mL6eZbPdx2NmSyzvQSMAcc" name="Brooks Ghost Max 3" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/mL6eZbPdx2NmSyzvQSMAcc-1920-80.png" mos="" align="middle" fullscreen="" width="890" height="575" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0DM3R7VD1?" target="_blank" rel="nofollow" data-dimension112="c2df5fcc-d2c0-11f1-9639-7d5af08a33f8" data-action="Deal Block" data-label="Ghost Max 3 (Men's)" data-dimension48="Ghost Max 3 (Men's)" data-dimension25="$109">Ghost Max 3 (Men's): was $159 now $109</a></strong><br />The Ghost Max 3 is a more cushioned and rockered alternative to the Ghost 17. The Ghost Max 4 has just come out, meaning the Ghost Max 3 is reduced by $50, with plenty of colors and sizes included in the sale.<a class="view-deal button" href="https://www.amazon.com/dp/B0DM3R7VD1?" target="_blank" rel="nofollow" data-dimension112="c2df5fcc-d2c0-11f1-9639-7d5af08a33f8" data-action="Deal Block" data-label="Ghost Max 3 (Men's)" data-dimension48="Ghost Max 3 (Men's)" data-dimension25="$109">View Deal</a></p></div><div class="product"><a data-dimension112="c2df60a8-d2c0-11f1-8324-df0cbc45e6cc" data-action="Deal Block" data-label="Glycerin Max (Women's)" data-dimension48="Glycerin Max (Women's)" data-dimension25="$149" href="https://www.amazon.com/Brooks-Womens-Glycerin-Peacoat-Ribbon/dp/B0D3B6HXJ7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:926px;"><p class="vanilla-image-block" style="padding-top:62.10%;"><img id="Y98AvyBg8eBD4Re2iRNXC6" name="Brooks Gycerin Max" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Y98AvyBg8eBD4Re2iRNXC6-1920-80.png" mos="" align="middle" fullscreen="" width="926" height="575" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Brooks-Womens-Glycerin-Peacoat-Ribbon/dp/B0D3B6HXJ7" target="_blank" rel="nofollow" data-dimension112="c2df60a8-d2c0-11f1-8324-df0cbc45e6cc" data-action="Deal Block" data-label="Glycerin Max (Women's)" data-dimension48="Glycerin Max (Women's)" data-dimension25="$149">Glycerin Max (Women's): was $199 now $149</a></strong><br />The original Glycerin Max is not just $50 cheaper than the Glycerin Max 2 thanks to this deal, but it's arguably better than the latest model because it's a bit lighter. This is the most cushioned model in the Brooks' line-up, and perfect for anyone who loves a comfortable running shoe.<a class="view-deal button" href="https://www.amazon.com/Brooks-Womens-Glycerin-Peacoat-Ribbon/dp/B0D3B6HXJ7" target="_blank" rel="nofollow" data-dimension112="c2df60a8-d2c0-11f1-8324-df0cbc45e6cc" data-action="Deal Block" data-label="Glycerin Max (Women's)" data-dimension48="Glycerin Max (Women's)" data-dimension25="$149">View Deal</a></p></div><div class="product"><a data-dimension112="c2df6120-d2c0-11f1-a95b-63a369414996" data-action="Deal Block" data-label="Hyperion Elite 5" data-dimension48="Hyperion Elite 5" data-dimension25="$149" href="https://www.amazon.com/dp/B0F4NG15WR?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:980px;"><p class="vanilla-image-block" style="padding-top:58.67%;"><img id="ZsxwPp8UrjYaq3Tu7V3wud" name="Brooks Hyperion Elite 5" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZsxwPp8UrjYaq3Tu7V3wud-1920-80.png" mos="" align="middle" fullscreen="" width="980" height="575" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>When it comes to running fast, carbon plate racers are the shoe to go for, but they're normally prohibitively expensive. Thanks to this $75 saving the Brooks Hyperion Elite 5 is under $200 in the Amazon sale. It's still not exactly cheap, but if you have PRs in mind, it will help get you there with its lightweight, propulsive design.<a class="view-deal button" href="https://www.amazon.com/dp/B0F4NG15WR?" target="_blank" rel="nofollow" data-dimension112="c2df6120-d2c0-11f1-a95b-63a369414996" data-action="Deal Block" data-label="Hyperion Elite 5" data-dimension48="Hyperion Elite 5" data-dimension25="$149">View Deal</a></p></div><h3 class="article-body__section" id="section-best-saucony-deals"><span>Best Saucony Deals</span></h3><div class="product"><a data-dimension112="c2df61e8-d2c0-11f1-9967-bb277f443bb4" data-action="Deal Block" data-label="Cohesion 14 Shoes (Women's)" data-dimension48="Cohesion 14 Shoes (Women's)" data-dimension25="$50" href="https://www.amazon.com/dp/B08CGR4YKG?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:58.99%;"><img id="pdjLV6pX6UWTGkcfsqaSE3" name="Cohesion 14 Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pdjLV6pX6UWTGkcfsqaSE3-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="410" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B08CGR4YKG?" target="_blank" rel="nofollow" data-dimension112="c2df61e8-d2c0-11f1-9967-bb277f443bb4" data-action="Deal Block" data-label="Cohesion 14 Shoes (Women's)" data-dimension48="Cohesion 14 Shoes (Women's)" data-dimension25="$50">Cohesion 14 Shoes (Women's): was $80 now $50</a></strong><br />The Saucony Cohesion 14 were already budget-friendly at $80, but now you can get a pair for even less. Shoppers on Amazon love these shoes for their comfortable and supportive design, earning these a 4.1-star rating.<a class="view-deal button" href="https://www.amazon.com/dp/B08CGR4YKG?" target="_blank" rel="nofollow" data-dimension112="c2df61e8-d2c0-11f1-9967-bb277f443bb4" data-action="Deal Block" data-label="Cohesion 14 Shoes (Women's)" data-dimension48="Cohesion 14 Shoes (Women's)" data-dimension25="$50">View Deal</a></p></div><div class="product"><a data-dimension112="c2df624c-d2c0-11f1-b2ec-11e535a9e1c3" data-action="Deal Block" data-label="Tide 2 Trainer (Men's)" data-dimension48="Tide 2 Trainer (Men's)" data-dimension25="$56" href="https://www.amazon.com/dp/B0D31XXWHZ?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1200px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="gPCzUDufYEii6Von4ywQm" name="image" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gPCzUDufYEii6Von4ywQm-1920-80.png" mos="" align="middle" fullscreen="" width="1200" height="1200" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0D31XXWHZ?" target="_blank" rel="nofollow" data-dimension112="c2df624c-d2c0-11f1-b2ec-11e535a9e1c3" data-action="Deal Block" data-label="Tide 2 Trainer (Men's)" data-dimension48="Tide 2 Trainer (Men's)" data-dimension25="$56">Tide 2 Trainer (Men's): was $100 now $56</a></strong><br />The Tide 2 is all about comfort for your everyday. It has soft, springy foam to make every step feel cushioned, a flexible plate to give you a little bounce and move with ease, <em>and</em> a breathable mesh upper to keep your feet cool. Basically, it’s perfect for walking, running errands, or just being on your feet all day without feeling sore.<a class="view-deal button" href="https://www.amazon.com/dp/B0D31XXWHZ?" target="_blank" rel="nofollow" data-dimension112="c2df624c-d2c0-11f1-b2ec-11e535a9e1c3" data-action="Deal Block" data-label="Tide 2 Trainer (Men's)" data-dimension48="Tide 2 Trainer (Men's)" data-dimension25="$56">View Deal</a></p></div><div class="product star-deal"><a data-dimension112="c2df62b0-d2c0-11f1-b672-abfae88a3776" data-action="Star Deal Block" data-label="Hurricane 24 (Men's)" data-dimension48="Hurricane 24 (Men's)" data-dimension25="$70" href="https://www.amazon.com/Saucony-Hurricane-Sneaker-Black-Shadow/dp/B0D31XQL4H" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1498px;"><p class="vanilla-image-block" style="padding-top:46.40%;"><img id="vxf7UD5T2Am7guVzFoFcZ4" name="Saucony Hurricane 24 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4-1920-80.jpg" mos="" align="middle" fullscreen="" width="1498" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Saucony-Hurricane-Sneaker-Black-Shadow/dp/B0D31XQL4H" target="_blank" rel="nofollow" data-dimension112="c2df62b0-d2c0-11f1-b672-abfae88a3776" data-action="Star Deal Block" data-label="Hurricane 24 (Men's)" data-dimension48="Hurricane 24 (Men's)" data-dimension25="$70">Hurricane 24 (Men's): was $80 now $70</a></strong><br />Running with the <a href="https://www.tomsguide.com/wellness/running/saucony-hurricane-24-review">Saucony Hurricane 24 </a>is like running on clouds. They use PWRRUN+ foam, which cushions your feet while still feeling springy. With a wide base and rocker design, it offers a stable and comfortable ride for longer or easy runs. The breathable mesh upper fits securely without being tight. The Hurricane 25 have replaced these shoes, but the 24 are the real bargain. <a class="view-deal button" href="https://www.amazon.com/Saucony-Hurricane-Sneaker-Black-Shadow/dp/B0D31XQL4H" target="_blank" rel="nofollow" data-dimension112="c2df62b0-d2c0-11f1-b672-abfae88a3776" data-action="Star Deal Block" data-label="Hurricane 24 (Men's)" data-dimension48="Hurricane 24 (Men's)" data-dimension25="$70">View Deal</a></p></div><div class="product"><a data-dimension112="c2df630a-d2c0-11f1-a069-8de46a5c3eea" data-action="Deal Block" data-label="Ride 18 (Men's)" data-dimension48="Ride 18 (Men's)" data-dimension25="$79" href="https://www.amazon.com/Saucony-Mens-Sneaker-BLACK-WHITE/dp/B0D31WZWT8" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1542px;"><p class="vanilla-image-block" style="padding-top:45.07%;"><img id="NmXRUrbSqDWhK8xTzQF7bf" name="Ride 18 (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/NmXRUrbSqDWhK8xTzQF7bf-1920-80.jpg" mos="" align="middle" fullscreen="" width="1542" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Saucony-Mens-Sneaker-BLACK-WHITE/dp/B0D31WZWT8" target="_blank" rel="nofollow" data-dimension112="c2df630a-d2c0-11f1-a069-8de46a5c3eea" data-action="Deal Block" data-label="Ride 18 (Men's)" data-dimension48="Ride 18 (Men's)" data-dimension25="$79">Ride 18 (Men's): was $145 now $79</a></strong><br />Comfort and support matter, and the <a href="https://www.tomsguide.com/wellness/fitness/i-ran-45-miles-in-the-saucony-ride-18-heres-my-verdict">Saucony Ride 18</a> delivers both. The soft, bouncy PWRRUN Plus foam feels light underfoot, helping to take the pressure off your joints as you build confidence. The stretchy mesh upper moves with your foot while the padded heel reduces rubbing that can cut runs short. Whether you’re lacing up for your first 5K or logging serious mileage, this shoe is a reliable all-rounder.<a class="view-deal button" href="https://www.amazon.com/Saucony-Mens-Sneaker-BLACK-WHITE/dp/B0D31WZWT8" target="_blank" rel="nofollow" data-dimension112="c2df630a-d2c0-11f1-a069-8de46a5c3eea" data-action="Deal Block" data-label="Ride 18 (Men's)" data-dimension48="Ride 18 (Men's)" data-dimension25="$79">View Deal</a></p></div><div class="product"><a data-dimension112="c2df636e-d2c0-11f1-a01a-f354a1da8b48" data-action="Deal Block" data-label="Triumph 23" data-dimension48="Triumph 23" data-dimension25="$89" href="https://www.amazon.com/Saucony-Triumph-Sneaker-Black-White/dp/B0DJWN776G" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="99qpJaU9RKTQSkGAmdZPrJ" name="saucony-mens-triumph-23-sneaker-whiteazu-4c83ebb7-41ff-452b-aa7e-9fe244156c64.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/99qpJaU9RKTQSkGAmdZPrJ-1920-80.jpg" mos="" align="middle" fullscreen="" width="500" height="500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Saucony Triumph 23 has a couple of key features to recommend it. One is that it's very comfortable and protective, and the other is its durability. That said, it's now discounted by 48%. It's also a lot cheaper than the <a href="https://www.tomsguide.com/wellness/running/i-ran-40-miles-in-the-saucony-triumph-24-and-its-a-return-to-form-for-the-popular-cushioned-running-shoe" data-dimension112="c2df636e-d2c0-11f1-a01a-f354a1da8b48" data-action="Deal Block" data-label="Triumph 23" data-dimension48="Triumph 23" data-dimension25="$89">Triumph 24</a>.<a class="view-deal button" href="https://www.amazon.com/Saucony-Triumph-Sneaker-Black-White/dp/B0DJWN776G" target="_blank" rel="nofollow" data-dimension112="c2df636e-d2c0-11f1-a01a-f354a1da8b48" data-action="Deal Block" data-label="Triumph 23" data-dimension48="Triumph 23" data-dimension25="$89">View Deal</a></p></div><h3 class="article-body__section" id="section-shop-more-deals"><span>Shop More Deals</span></h3><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Sneakers%2C+running+shoes%2C+sandals&amp;brands=Hoka%2CSkechers%2CAsics&amp;view_mode=carousel&amp;widget_title=Top+Deals+Handpicked+by+Our+Editors&amp;widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&amp;bg_color=light_blue" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters {      display: flex;      gap: 12px;      justify-content: center;      flex-wrap: wrap;    }    .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);      display: -webkit-box;      -webkit-line-clamp: 2;      -webkit-box-orient: vertical;      overflow: hidden;    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    .tg-df-container .tg-df-card-cta.tg-df-cta-savings-squad {      background-color: #3c8d0d;    }    .tg-df-card:hover .tg-df-card-cta.tg-df-cta-savings-squad,    .tg-df-card-cta.tg-df-cta-savings-squad:hover {      background-color: #2b6509;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 0;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 0 16px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }            .tg-df-filters {        width: calc(100% + 32px);        margin: 0 -16px;        padding: 0 16px 4px 16px;        display: flex;        justify-content: flex-start;        gap: 8px;        flex-wrap: nowrap;        overflow-x: auto;        -webkit-overflow-scrolling: touch;        scrollbar-width: none;      }      .tg-df-filters::after {        content: "";        display: block;        flex: 0 0 8px;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }            .tg-df-sort-wrapper {        flex: 0 0 max(42%, 130px);        min-width: 0;      }      .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;        -webkit-line-clamp: 3;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        -webkit-line-clamp: 3;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 16px;      text-align: center;      width: 100%;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: #f8fafc;      border-color: #cbd5e1;    }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right {      background-color: rgba(255, 255, 255, 0.4);      border: none;      box-shadow: none;      backdrop-filter: blur(4px);      -webkit-backdrop-filter: blur(4px);    }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right { right: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-right { right: 0; }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left:hover,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);      border: none;    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-carousel-roundels::after {      content: "";      flex: 0 0 32px;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;      transition: font-weight 0.2s;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-label {      font-weight: 700;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;      display: inline-flex;      align-items: center;      justify-content: center;      min-height: 36px;      box-sizing: border-box;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::after {      content: "";      flex: 0 0 32px;    }    .tg-df-grid-wrapper {      position: relative;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card {      flex: 0 0 auto;      width: 100px;      border-radius: 15px;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      border: 2px solid #1e293b;      background: white;      color: #1e293b;      display: flex;      flex-direction: column;      justify-content: center;      align-items: center;      font-weight: 600;      font-size: 14px;      cursor: pointer;      padding: 16px;      text-align: center;      transition: all 0.2s;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card:hover {      background: #1e293b;      color: white;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      -webkit-line-clamp: 2;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {      -webkit-line-clamp: 3;    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.45);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #5aaf0b; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #4a9109; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>          \x3C/div>          \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">      \x3Cdiv class="tg-df-top-bar">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>                \x3Cdiv class="tg-df-settings-wrapper">          \x3Cbutton type="button" class="tg-df-settings-btn" aria-label="Settings" id="tg-df-settings-toggle">            \x3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20">                \x3Cpath d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.73 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .43-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.49-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/>            \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-settings-dropdown-backdrop" id="tg-df-settings-backdrop">\x3C/div>          \x3Cdiv class="tg-df-settings-dropdown" id="tg-df-settings-panel">            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Search Region\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-region-select">                \x3Coption value="auto">🌍 Auto-detect\x3C/option>                \x3Coption value="US">🇺🇸 United States (US)\x3C/option>                \x3Coption value="GB">🇬🇧 United Kingdom (UK)\x3C/option>                \x3Coption value="CA">🇨🇦 Canada (CA)\x3C/option>                \x3Coption value="AU">🇦🇺 Australia (AU)\x3C/option>                \x3Coption value="DE">🇩🇪 Germany (DE)\x3C/option>                \x3Coption value="FR">🇫🇷 France (FR)\x3C/option>                \x3Coption value="IT">🇮🇹 Italy (IT)\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Retailer\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-retailer-select">                \x3Coption value="">All Retailers\x3C/option>                \x3Coption value="Amazon">Amazon\x3C/option>                \x3Coption value="Walmart">Walmart\x3C/option>                \x3Coption value="Best Buy">Best Buy\x3C/option>                \x3Coption value="Target">Target\x3C/option>                \x3Coption value="John Lewis">John Lewis\x3C/option>                \x3Coption value="Currys">Currys\x3C/option>                \x3Coption value="Argos">Argos\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Offer Type\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-offer-type-select">                \x3Coption value="">All Offers\x3C/option>                \x3Coption value="amazon_prime">Amazon Prime\x3C/option>                \x3Coption value="recommended_promo">Recommended Promo\x3C/option>                \x3Coption value="amazon_lightning">Amazon Lightning Deal\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Result Count\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-rows-select">                \x3Coption value="3">3 Items\x3C/option>                \x3Coption value="4">4 Items\x3C/option>                \x3Coption value="6">6 Items\x3C/option>                \x3Coption value="12" selected>12 Items\x3C/option>                \x3Coption value="24">24 Items\x3C/option>                \x3Coption value="48">48 Items\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Deal Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Only show products with active offers or previous prices (was_price)\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-deal-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Editor Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Enable multi-select to copy deals to CMS\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-editor-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">View Mode\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-view-mode-select">                \x3Coption value="auto">Auto Collection\x3C/option>                \x3Coption value="carousel">Carousel\x3C/option>                \x3Coption value="savings_squad">Savings Squad\x3C/option>                \x3Coption value="grid">Grid (Columns)\x3C/option>                \x3Coption value="row">Row (List)\x3C/option>              \x3C/select>            \x3C/div>          \x3C/div>        \x3C/div>      \x3C/div>      \x3Cdiv class="tg-df-filters">        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M9 3L5 6.99h3V14h2V6.99h3L9 3zm7 14.01V10h-2v7.01h-3L15 21l4-3.99h-3z"/>          \x3C/svg>          \x3Cselect class="tg-df-sort-select" aria-label="Sort Deals">            \x3Coption value="date_desc">Newest First\x3C/option>            \x3Coption value="best_match">Sort by: Match\x3C/option>            \x3Coption value="price_asc">Price Low to High\x3C/option>            \x3Coption value="price_desc">Price High to Low\x3C/option>            \x3Coption value="discount_desc">Biggest Discount\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>        \x3C/div>      \x3C/div>    \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();            if (['carousel', 'carousel-compact', 'auto', 'grid', 'row'].includes(this.getViewMode())) { this.loadCarouselSpreadsheet(); }        }        getViewMode() {          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          if (mode === 'carousel' || mode === 'auto' || mode === 'grid' || mode === 'row') {             if (mode === 'carousel') this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container') && mode === 'carousel') {               this.root.classList.add('is-carousel');             } else if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Everything';             if (this.discountFilter && !params.has('min_discount_ratio')) {               this.discountFilter.value = '5';             }          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (params.has('bg_color')) {            const bg = params.get('bg_color');            if (bg === 'white') {              this.root.style.setProperty('background-color', '#ffffff', 'important');            } else if (bg === 'transparent') {              this.root.style.setProperty('background-color', 'transparent', 'important');            } else if (bg === 'light_blue') {              this.root.style.setProperty('background-color', '#E7F0FF', 'important');            }          } else {             this.root.style.removeProperty('background-color');          }                    if (params.has('view_mode')) {            if (this.viewModeSelect) {              this.viewModeSelect.value = params.get('view_mode');            } else {              this.viewModeOverride = params.get('view_mode');            }          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'discount_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            this.searchInput.value = this.currentQuery;          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'discount_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const roundels = this.root.querySelectorAll('.tg-df-carousel-cat.original-hardcoded');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              if (this.getViewMode() === 'savings_squad' && this.autocompleteDropdown && this.airedaleTags && query.length > 0) {                 const matches = this.airedaleTags.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase()).slice(0, 5);                 if (matches.length > 0) {                    this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                    this.autocompleteDropdown.classList.add('active');                 } else {                    this.autocompleteDropdown.classList.remove('active');                 }              } else if (this.autocompleteDropdown) {                 this.autocompleteDropdown.classList.remove('active');              }              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  this.deals = [];                  this.render();                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                this.activeDealTag = null;                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });              this.activeDealTag = null;              this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.fetchDeals(query);              }            });          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = this.viewModeSelect.value === 'savings_squad' ? 'date_desc' : 'discount_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }                async loadCarouselSpreadsheet() {          try {              const parseCSVRow = (str) => {                  let result = [], cur = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (inQuotes) {                          if (char === '"') {                              if (str[i + 1] === '"') { cur += '"'; i++; }                              else { inQuotes = false; }                          } else { cur += char; }                      } else {                          if (char === '"') { inQuotes = true; }                          else if (char === ',') { result.push(cur); cur = ''; }                          else { cur += char; }                      }                  }                  result.push(cur); return result;              };              const parseCSV = (str) => {                  const rows = []; let curRow = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (char === '"') inQuotes = !inQuotes;                      if ((char === '\n' || char === '\r') && !inQuotes) {                          if (char === '\r' && str[i+1] === '\n') i++;                          if (curRow) rows.push(parseCSVRow(curRow));                          curRow = '';                      } else { curRow += char; }                  }                  if (curRow) rows.push(parseCSVRow(curRow));                  return rows;              };              const preloadedCSV = decodeURIComponent(escape(atob("LCwxLDIsMyw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNQ0KUm91bmRlbCB0ZXh0LEFsbCxUVnMsRm9vdHdlYXIsQXBwYXJlbCxNYXR0cmVzZXMsQXBwbGlhbmNlcyxXZWFyYWJsZSB0ZWNoLEhlYWRwaG9uZXMsU21hcnQgSG9tZSxTcGVha2VycyxMYXB0b3BzLFRhYmxldHMsQ29tcHV0aW5nLFBob25lcyxHYW1pbmcsTGVnbw0KUm91bmRlbCBpbWFnZSxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL2FpLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3R2cy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvN2IzYTIyNGIwNzk2M2M2MjdiNmI5MDliZDc4MzM4MzZlMDJmZjgxOS5qcGcud2VicCxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy84NGRhYzVkNDhlZDJkNDQ4NTU5ZWJhNjdhY2U4MzE0Y2M2N2NjZDk0LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vcHJvZHVjdHMvY2Fyb3VzZWwvbWF0dHJlc3Nlcy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvNzY4ZTk3Y2ViMDcxODAxZmFlMjA5MTBkMDgyMGIxNmY3NDdhZjkzOS5qcGcud2VicCxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3dlbGxuZXNzLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL2hlYWRwaG9uZXMuanBnLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzg5NTM1YmVlYmUyMGRiYmQ0YTM0NmQ2ZDZiZGZlOTFkOGE4ODRhMjEuanBnLndlYnAsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9hdWRpby5qcGcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9sYXB0b3BzLmpwZyxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy8yMzk3NTY0ZWQ3YTVmZjk0N2U5YjZiMzBlNTRmNDc0OTRiODQxZjg5LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vcHJvZHVjdHMvY2Fyb3VzZWwvY29tcHV0aW5nLmpwZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3Bob25lcy5wbmcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9nYW1pbmcucG5nLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzRmNmM2MjFjYWMwYmMxYTg1ZDU5M2UzNTk0YmE1YjM0OWVmZmQyOTIuanBnLndlYnANClNlYXJjaCBRdWVyeSxFdmVyeXRoaW5nLFRlbGV2aXNpb25zLCJTbmVha2VycywgcnVubmluZyBzaG9lcywgc2FuZGFscyIsQ2xvdGhpbmcsTWF0dHJlc3NlcyxIb21lIEFwcGxpYW5jZXMsV2VhcmFibGVzICYgRml0bmVzcyBUZWNoLEhlYWRwaG9uZXMsSG9tZSBUZWNoLFNwZWFrZXJzLExhcHRvcHMsVGFibGV0cyxDb21wdXRpbmcsUGhvbmVzLEdhbWluZyxDb25zdHJ1Y3Rpb24gVG95cw0KRGlzY291bnQgQW1vdW50LG1pbiA1JSxtaW4gMTAlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUNClByaWNlIFJhbmdlLCwsLCxtaW4gJDQwMCwsLCxtaW4gJDI1LCxtaW4gJDMwMCwsLG1pbiAkMTAwLCwNCkJyYW5kIFNlbGVjdGlvbiwsLCwsLCwsLCwsLCwsLCwNCkZpbHRlciBidXR0b25zLCwsLCwsLCwsLCwsLCwsLA0KMSxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMNCjIsQW1hem9uIGRlYWxzLFVuZGVyICQxMDAwLDUwJSBvZmYsQWRpZGFzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsNTAlIG9mZixBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscw0KMyxPdmVyICQ0MDAsVW5kZXIgJDUwMCxIb2thLE5pa2UsU2FhdHZhLE5pbmphLDQwJSBvZmYsSkxhYiwsSkJMLERlbGwsLEFzdXMsQXBwbGUsQ29uc29sZXMsU3RhciBXYXJzDQo0LFVuZGVyICQxMDAwLDUwJSBvZmYsU2tlY2hlcnMsVW5kZXIgQXJtb3VyLEhlbGl4LFNoYXJrLEdhcm1pbixBbmtlciBTb3VuZGNvcmUsUmluZyxTb25vcyxBcHBsZSxBcHBsZSxUUC1saW5rLFNhbXN1bmcsQWNjZXNzb3JpZXMsVW5kZXIgJDI1DQo1LFVuZGVyICQ1MDAsTEcsQXNpY3MsQ29sdW1iaWEsRHJlYW1DbG91ZCxLZXVyaWcsQXBwbGUsU29ueSxHb3ZlZSxUcmliaXQsTGVub3ZvLFNhbXN1bmcsRWVybyxHb29nbGUsR2FtZXMsVW5kZXIgJDUwDQo2LDUwJSBvZmYsU2Ftc3VuZyxOaWtlLFBhdGFnb25pYSxOZWN0YXIsRGUnTG9uZ2hpLEFtYXpmaXQsQXBwbGUsS2FzYSBzbWFydCxTb255LEFsaWVud2FyZSxUQ0wsTmV0Z2VhcixNb3Rvcm9sYSxOaW50ZW5kbyxCb3RhbmljYWxzDQo3LEFtYXpvbixIaXNlbnNlLE5ldyBCYWxhbmNlLEFyYyd0ZXJ5eCxUZW1wdXItcGVkaWMsRHlzb24sRml0Yml0LEJlYXRzLFBoaWxpcHMgSHVlLEFua2VyLEFjZXIsT25lUGx1cyxEZWxsLE9uZVBsdXMsU29ueSxEaXNuZXkNCjgsQXBwbGUsVENMLEFkaWRhcyxDYXJoYXJ0dCxCZWFyLEJpc3NlbGwsU2Ftc3VuZyxFYXJmdW4sQmxpbmssQmVhdHMsTVNJLE1pY3Jvc29mdCxBY2VyLE5vdGhpbmcsWGJveCxNYXJ2ZWwNCjksLFNvbnksU2F1Y29ueSxUaGUgTm9ydGggRmFjZSxTaWVuYSxOdXRyaWJ1bGxldCxPdXJhLFNhbXN1bmcsR29vZ2xlIE5lc3QgLE1hcnNoYWxsLFNhbXN1bmcsTGVub3ZvLExlbm92bywsLFBva2Vtb24NCjEwLCxSb2t1LEJpcmtlbnN0b2NrLENSWiBZb2dhLFdpbmtCZWRzLEJsYWNrIGFuZCBEZWNrZXIsUmluZ2Nvbm4sQ01GLEV1ZnksU2Ftc3VuZyxNaWNyb3NvZnQsUmVNYXJrYWJsZSxBbGllbndhcmUsLCwNCjExLCwsQnJvb2tzLFRoZSBHeW0gUGVvcGxlLEJyb29rbHluIGJlZGRpbmcsTmVzcHJlc3NvLCwxTW9yZSxBcmxvLCxSYXplciwsQ29yc2FpciwsLA0KMTIsLCxDcm9jcywsRWlnaHQgU2xlZXAsQ3Vpc2luYXJ0LCxKQkwsLCwsLEhQLCwsDQpOb3RlcywsLCwsLCwsLCwsLCwsLCwNCiwsIlByaW9yaXRpc2UgYmlnZ2VzdCAlLyQgZGlzY291bnQsIFR2cyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiB0aGUgbW9zdCBwb3B1bGFyIGV2ZW4gaWYgdGhleSBhcmUgc3RpbGwgZXhwZW5zaXZlIiwiTm8gcGF0dGVybiB0byBwcmljaW5nL2Rpc2NvdW50LCByZWFkZXJzIG1haW5seSBzaG9wIGJ5IGJyYW5kL3JlY29nbmlzYWJsZSBzaG9lcyIsIk5vIHBhdHRlcm4gdG8gcHJpY2luZy9kaXNjb3VudCwgcmVhZGVycyBtYWlubHkgc2hvcCBieSBicmFuZCIsIkEgbGFiZWwgd2lsbCBkZWZpbml0ZWx5IGhlbHAgaGVyZSBlLmcuIGJlc3QgZm9yIHNpZGUgc2xlZXBlciwgYmVzdCBtZW1vcnkgZm9hbSIsIkFwcGxpYW5jZXMgaXMgYSBiaWcgY2F0ZWdvcnksIGlzIGl0IHBvc3NpYmxlIHRvIHNwbGl0IGludG8ga2l0Y2hlbiBhcHBsaWFuY2VzLCBmbG9vcmNhcmUsIGFpciBoZWFsdGgvY29vbGluZz8gT3Igc2ltaWxhciIsIkZvY3VzIG9uIHZhbHVlIGZvciBtb25leSwgR2FybWlucyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiBwb3B1bGFyIGV2ZW4gdGhvdWdoIHRoZXkgYXJlIHN0aWxsICQ1MDAiLCwsLCxJbmNsdWRlIEtpbmRsZXMsSSB3b3VsZCBpbmNsdWRlIHdpZmkgcm91dGVycyBoZXJlIGluc3RlYWQgb2Ygc21hcnQgaG9tZSxDYW4gd2Ugc3VyZmFjZSBwaG9uZSBwcm92aWRlciBkZWFscz8gVC1tb2JpbGUgYW5kIHZlcml6b24gd291bGQgbWFrZSBhIGxvdCBtb3JlIG1vbmV5IHRoYW4gQW1hem9uLCwNCiwsaGF2aW5nIGEgJ2Jlc3QgZm9yJyBsYWJlbCB3b3VsZCBiZSBoZWxwZnVsIGUuZy4gYmVzdCBmb3IgYnJpZ2h0IHJvb20sQ2FuIHdlIHN0b3Aga2lkcyBzaG9lcyBmcm9tIHB1bGxpbmcgdGhyb3VnaD8sIldpbGwgdGhpcyBpbmNsdWRlIGFjY2Vzc29yaWVzIGUuZy4gY2FwcywgYmFncywgaWYgc28gbWFrZSBzdXJlIHRoZXNlIGFyZSBtaXhlZCB0aHJvdWdob3V0IGNsb3RoaW5nIGRlYWxzIixXaWxsIHRoaXMgaW5jbHVkZSB0b3BwZXJzIGFuZCBwaWxsb3dzPyBTZWVpbmcgbW9yZSBtb21lbnR1bSB3aXRoIHRoaXMgY2F0ZWdvcnkgcmVjZW50bHkgc28gYSBiZWRkaW5nIHRhYiBtaWdodCB3b3JrLCwiTmVlZCB0byBtYWtlIHN1cmUgYmFuZHMsIHNjcmVlbiBwcm90ZWN0b3JzIGV0Yy4gZG9uJ3QgcHVsbCBpbnRvIGhlcmUiLCwsLCwsLCwsDQosLCJQcmlvcml0aXNlIDY1JycgYW5kIDU1JyBpbmNoIFRWcywgdGhlbiBiaWdnZXIgc2NyZWVucyBiZWZvcmUgdGhlIHNtYWxsZXIgc2l6ZXMiLCwsUXVlZW4gaXMgdGhlIG1vc3QgcG9wdWxhciBzaXplIGluIHRoZSBVUyAtIHByaW9yaXRpc2UgZGVhbHMgZm9yIHRoaXMgc2l6ZSwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpDYXRlZ29yaWVzIHRvIGNvbnNpZGVyLCxQcm9kdWN0cyBpbmNsdWRlZCwsLCwsLCwsLCwsLCwsDQpVbmRlciAkNTA/LCxBaXIgdGFncywsLCwsLCwsLCwsLCwsDQosLFBvcnRhYmxlIGNoYXJnZXJzL3dpcmVsZXNzIGNoYXJnZXJzLCwsLCwsLCwsLCwsLCwNCiwsIldhdGVyIGJvdHRsZXMgKHN0YW5sZXlzLCBPd2FsYSwgSHlkcm8gZmxhc2ssIFlldGkpIiwsLCwsLCwsLCwsLCwsDQosLEhhbmQgaGVsZCBmYW5zLCwsLCwsLCwsLCwsLCwNCiwsLCwsLCwsLCwsLCwsLCwNCmhvbWUgb2ZmaWNlLCxvZmZpY2UgY2hhaXJzLCwsLCwsLCwsLCwsLCwNCiwsc3RhbmRpbmcgZGVza3MsLCwsLCwsLCwsLCwsLA0KLCxtb25pdG9ycywsLCwsLCwsLCwsLCwsDQosLEtleWJvYXJkcywsLCwsLCwsLCwsLCwsDQosLGRvY2tpbmcgc3RhdGlvbiwsLCwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpHYW1pbmcsLENvbnNvbGVzLCwsLCwsLCwsLCwsLCwNCiwsQWNjZXNzb3JpZXMsLCwsLCwsLCwsLCwsLA0KLCxHYW1lcywsLCwsLCwsLCwsLCwsDQosLENvdWxkIGluY2x1ZGUgTGVnbz8sLCwsLCwsLCwsLCwsLA==")));              const text = preloadedCSV;              const parsed = parseCSV(text);                            const rowsByName = {};              let filterStart = -1;              parsed.forEach((rc, i) => {                 if (rc && rc.length > 0 && rc[0]) rowsByName[rc[0]] = rc;                 if (rc && rc.length > 0 && rc[0] === 'Filter buttons') filterStart = i;              });                            const cols = [];              if(rowsByName['Roundel text']) {                const headerRow = rowsByName['Roundel text'];                for(let col = 1; col < headerRow.length; col++) {                   let label = headerRow[col];                   if (!label) continue;                                      let q = rowsByName['Search Query'] && rowsByName['Search Query'][col] ? rowsByName['Search Query'][col] : '';                   let img = rowsByName['Roundel image'] && rowsByName['Roundel image'][col] ? rowsByName['Roundel image'][col] : '';                   let ds = rowsByName['Discount Amount'] && rowsByName['Discount Amount'][col] ? rowsByName['Discount Amount'][col] : '';                   let pr = rowsByName['Price Range'] && rowsByName['Price Range'][col] ? rowsByName['Price Range'][col] : '';                   let rt = rowsByName['Retailer'] && rowsByName['Retailer'][col] ? rowsByName['Retailer'][col] : '';                   let ot = rowsByName['Offer Type'] && rowsByName['Offer Type'][col] ? rowsByName['Offer Type'][col] : '';                                      let filters = [];                   if(filterStart > 0) {                     for(let r = filterStart + 1; r < parsed.length; r++) {                         if(!parsed[r] || parsed[r][0] === 'Notes' || parsed[r][0] === 'Categories to consider') break;                         let f = parsed[r][col];                         if(f) filters.push(f);                     }                   }                   cols.push({ label, img, q, ds, pr, rt, ot, filters });                }              }              this.carouselData = cols;              if (this.carouselData && this.carouselData.length > 0) {                 const isMatched = this.carouselData.some(c => c.q === this.currentQuery || c.label === this.currentQuery);                 if (!isMatched) {                    const first = this.carouselData[0];                    this.currentQuery = first.q || first.label;                    if (this.priceFilter) this.priceFilter.value = 'all';                    if (this.customPriceMin) this.customPriceMin.value = '';                    if (this.customPriceMax) this.customPriceMax.value = '';                    let dPr = first.pr || 'all';                    if (typeof dPr === 'string' && dPr !== 'all') {                       let prLower = dPr.toLowerCase();                       if (prLower.includes('min') || prLower.includes('over')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else if (prLower.includes('max') || prLower.includes('under')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       }                    }                    let dAm = '0';                    if(first.ds && typeof first.ds === 'string') {                       let m = first.ds.match(/(\d+)/);                       if(m) dAm = m[1];                    }                    if (this.discountFilter) this.discountFilter.value = dAm;                    if (this.offerTypeSelect) this.offerTypeSelect.value = first.ot || '';                    if (this.retailerSelect) this.retailerSelect.value = first.rt || '';                    this.selectedBrands = [];                    if (this.brandDropdown) {                        const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                        chks.forEach(chk => chk.checked = false);                    }                    if (this.searchInput) this.searchInput.value = this.currentQuery;                 }              }              this.renderCarouselUI();          } catch(e){ console.warn(e); }        }                renderCarouselUI() {           const roundelWrapper = this.root.querySelector('.tg-df-carousel-roundels');           if(!roundelWrapper || !this.carouselData) return;                      let html = '';           this.carouselData.forEach(r => {              const q = r.q || r.label;              const isActive = (this.currentQuery === q || this.currentQuery === r.label) ? 'active' : '';              const imgHtml = r.img ? `\x3Cimg src="${r.img}" alt="${r.label}" />` : `\x3Csvg width="32" height="32" fill="#1F69FF" viewBox="0 0 24 24">\x3Cpath d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/>\x3C/svg>`;              html += `                \x3Cdiv class="tg-df-roundel tg-df-carousel-cat ${isActive}" data-label="${this.escapeHTML(r.label)}">                  \x3Cdiv class="tg-df-roundel-img-box">${imgHtml}\x3C/div>                  \x3Cspan class="tg-df-roundel-label">${this.escapeHTML(r.label)}\x3C/span>                \x3C/div>              `;           });           roundelWrapper.innerHTML = html;                      // Rebind clicks           const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');           roundels.forEach(rNode => {             rNode.addEventListener('click', () => {                const r = this.carouselData.find(c => c.label === rNode.getAttribute('data-label'));                 if(!r) return;                                  if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: r.label,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = r.q || r.label;                const labelTitle = this.root.querySelector('#tg-df-carousel-title-label');                if (labelTitle) labelTitle.textContent = 'Best ' + this.currentQuery;                if (this.priceFilter) this.priceFilter.value = 'all';                if (this.customPriceMin) this.customPriceMin.value = '';                if (this.customPriceMax) this.customPriceMax.value = '';                let dPr = r.pr || 'all';                if (typeof dPr === 'string' && dPr !== 'all') {                   let prLower = dPr.toLowerCase();                   if (prLower.includes('min') || prLower.includes('over')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMin) this.customPriceMin.value = m[1];                   } else if (prLower.includes('max') || prLower.includes('under')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMax) this.customPriceMax.value = m[1];                   }                }                                let discountAmount = '0';                if(r.ds && typeof r.ds === 'string') {                   let m = r.ds.match(/(\d+)/);                   if(m) discountAmount = m[1];                }                if (this.discountFilter) this.discountFilter.value = discountAmount;                if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                                // Clear brands                    this.selectedBrands = [];                    if (this.brandDropdown) {                    const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                    chks.forEach(chk => chk.checked = false);                }                                if (this.searchInput) this.searchInput.value = this.currentQuery;                                roundels.forEach(ro => ro.classList.remove('active'));                if (rNode) rNode.classList.add('active');                                this.renderCarouselFilters(r);                this.fetchDeals(this.currentQuery);             });           });                      // Auto-highlight active           const activeR = this.carouselData.find(c => c.q === this.currentQuery || c.label === this.currentQuery);           if(activeR) this.renderCarouselFilters(activeR);        }                renderCarouselFilters(r) {           const filtersWrap = this.root.querySelector('.tg-df-carousel-filters-wrap');           if(!filtersWrap) return;                      let html = `\x3Cbutton class="tg-df-carousel-filter-btn" data-type="all">All\x3C/button>`;                      r.filters.forEach(f => {              let fL = f.toLowerCase();              let icon = '';              let logic = `data-type="custom" data-v="${this.escapeHTML(f)}"`;              if (fL === 'amazon deals' || fL === 'prime deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>`;              } else if (fL === 'lightning deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>`;              } else {                 if (fL.includes('lightning')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-zap">\x3Cpolygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2">\x3C/polygon>\x3C/svg>`;                 } else if (fL.includes('% off')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>`;                 } else if (fL.includes('under') || fL.includes('min ')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>`;                 }                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>${icon} ${this.escapeHTML(f)}\x3C/button>`;              }           });                      filtersWrap.innerHTML = html;                      const btns = filtersWrap.querySelectorAll('button');           btns.forEach(b => {             b.addEventListener('click', () => {                const type = b.getAttribute('data-type');                if (type === 'custom') {                   const v = b.getAttribute('data-v');                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-custom-${(v||'').toLowerCase().replace(/[^a-z0-9]+/g, '-')}`, name: 'Custom Filter', label: v });                }                if (type === 'all') {                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: 'filter-clear-all', name: 'Clear all', label: 'Clear all filters' });                   // reset everything                   btns.forEach(btn => btn.classList.remove('active'));                   b.classList.add('active');                                      // Reset prices                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   if (this.brandDropdown) {                     const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                     chks.forEach(chk => chk.checked = false);                   }                } else {                   const v = b.getAttribute('data-v');                   const fL = v.toLowerCase();                                      let mapRet = ['amazon', 'walmart', 'best buy', 'target', 'john lewis', 'currys', 'argos'];                   const getCategory = (s) => {                      if (s === 'lightning deals' || s === 'amazon deals' || s === 'prime deals') return 'offer';                      if (s.includes('% off')) return 'discount';                      if (s.includes('under') || s.includes('over') || s.includes('min') || s.includes('max')) return 'price';                      if (mapRet.includes(s)) return 'retailer';                      return 'brand';                   };                   const cat = getCategory(fL);                   const wasActive = b.classList.contains('active');                   if (cat !== 'brand') {                      btns.forEach(btn => {                          if (btn === b) return;                          if (btn.getAttribute('data-type') === 'all') return;                          const bV = btn.getAttribute('data-v');                          if (!bV) return;                          if (getCategory(bV.toLowerCase()) === cat) btn.classList.remove('active');                      });                   }                   if (wasActive) b.classList.remove('active');                   else b.classList.add('active');                   let anyActive = Array.from(btns).some(btn => btn !== btns[0] && btn.classList.contains('active'));                   if (!anyActive) {                       btns[0].click();                       return;                   } else {                       btns[0].classList.remove('active');                   }                                      if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   btns.forEach(btn => {                       if (!btn.classList.contains('active') || btn.getAttribute('data-type') === 'all') return;                       const vv = btn.getAttribute('data-v');                       const vl = vv.toLowerCase();                                              if (vl === 'lightning deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_lightning';                       } else if (vl === 'amazon deals' || vl === 'prime deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_prime';                       } else if (vl.includes('% off')) {                          let m = vl.match(/(\d+)%/);                          if (m && this.discountFilter) this.discountFilter.value = m[1];                       } else if (vl.includes('under') || vl.includes('max')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       } else if (vl.includes('min') || vl.includes('over')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else {                          let foundR = mapRet.find(x => x === vl);                          if (foundR) {                             let realR = ['Amazon', 'Walmart', 'Best Buy', 'Target', 'John Lewis', 'Currys', 'Argos'].find(x => x.toLowerCase() === vl);                             if (this.retailerSelect) this.retailerSelect.value = realR;                          } else {                             this.selectedBrands.push(vv);                          }                       }                   });                                      if (this.brandDropdown) {                       const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                       chks.forEach(c => c.checked = this.selectedBrands.includes(c.value));                   }                                      if (r.pr && typeof r.pr === 'string') {                       let prL = r.pr.toLowerCase();                       if (prL.includes('under $')) {                           let m = prL.match(/under \$(\d+)/i);                           if (m && this.customPriceMax && !this.customPriceMax.value) this.customPriceMax.value = m[1];                       }                   }                }                                this.fetchDeals(this.currentQuery);             });           });                      // default to highlighting first           btns[0].classList.add('active');        }async fetchDeals(query, append = false) {          if (!append) {             this.showLoading();             this.deals = [];             this.displayLimit = this.getRowsLimit();          } else {             this.displayLimit += this.getRowsLimit();          }                    try {            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad(append);            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query, append);               } else {                 await this.fetchHawkDeals(query, append);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query, append);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const url = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let dynamicBrandsCounts = {};                    targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                   dynamicBrandsCounts[data.brand] = (dynamicBrandsCounts[data.brand] || 0) + 1;                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || ''                });             });          });                    const airedaleBrandsList = Object.keys(dynamicBrandsCounts).map(b => ({              formatted_value: b,              count: dynamicBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query, append = false) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (append && this.deals.length > 0) {            url.searchParams.append('offset', this.deals.length.toString());          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : (this.getViewMode() === 'savings_squad' ? 'date_desc' : 'discount_desc');          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin-top:8px;">${_div}                ${_div}              ${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)} (${this.airedaleTagCounts[tag] || 0})${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = isSavingsSquadMode ? 'View Deal' : 'Check Price';              if (isSavingsSquadMode) {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                  ${_div}                `;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = `                \x3Cdiv class="tg-df-card-merchant-wrapper">                  \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                ${_div}                \x3Cdiv class="tg-df-card-price-group">                  ${isSavingsSquadMode ? '' : `                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                  `}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description">\x3Cp>${this.escapeHTML(deal.description)}${_p}${_div}` : ''}                      ${_div}                    ${_div}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>${deal.isCheckPrice ? 'Check Price' : 'View Deal'}${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cp style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 12px; line-height: 1.4;">${this.escapeHTML(deal.description)}${_p}` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${priceGroupHtml}                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta ${isSavingsSquadMode ? 'tg-df-cta-savings-squad' : ''}" style="text-decoration: none;">${ctaText}${_a}                  ${_div}                ${_div}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit || ((this.getViewMode() === 'carousel' || this.getViewMode() === 'auto') && displayDeals.length > 0 && displayDeals.length % ((this.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12) === 0)) {            if (this.getViewMode() === 'carousel') {               dealsHtml += `                 \x3Cbutton type="button" class="tg-df-load-more-card tg-df-load-more">                   \x3Csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-bottom: 8px;">\x3Cpath d="M5 12h14">\x3C/path>\x3Cpath d="m12 5 7 7-7 7">\x3C/path>\x3C/svg>                   Load More                 ${_button}               `;            } else {               dealsHtml += `                 \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                   \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer; display: flex; align-items: center;">Load More${_button}                 ${_div}               `;            }          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }                    let gridWrapper = this.grid.parentElement;          if (gridWrapper && gridWrapper.classList.contains('tg-df-grid-wrapper')) {             let rightChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-right');             let leftChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-left');             if (this.getViewMode() === 'carousel') {                 // The observer set up in setupScrollListeners handles visibility.                 if (rightChevron) rightChevron.style.display = 'flex';                 if (leftChevron) leftChevron.style.display = 'none'; // reset correctly             } else {                 if (rightChevron) rightChevron.style.display = 'none';                 if (leftChevron) leftChevron.style.display = 'none';             }          }                    const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', async () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              if (displayDeals.length <= this.displayLimit) {                 loadMoreBtn.innerHTML = `                  <svg class="tg-df-spinner" style="width: 16px; height: 16px; display: inline-block; vertical-align: middle; margin-right: 8px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" d="M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48l2.83-2.83"/></svg>                  Loading...                 `;                 loadMoreBtn.disabled = true;                 await this.fetchDeals(this.currentQuery, true);              } else {                 this.displayLimit += this.getRowsLimit();                 this.render();              }            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            setTimeout(() => {               if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');               document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));            }, 50);          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/running/25-best-fall-running-shoe-deals-get-up-to-50-percent-off-new-balance-nike-and-hoka</link>
                                                                            <description>
                            <![CDATA[ From Brooks to Saucony, these are the best running shoe deals you can shop right now from major brands. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">fBNnZM7FCDMw3ukuqQXpgc</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/4uC9Qfgqx7zRMJSQ2qkZ7F-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 28 Oct 2026 11:54:25 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Running]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                                                                <author><![CDATA[ millie.daviswilliams@futurenet.com (Millie Davis-Williams) ]]></author>                    <dc:creator><![CDATA[ Millie Davis-Williams ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/WU6pa7hKuxs5ScCoqcXYWA-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Millie is a Deals Editor at Tom&#039;s Guide specializing in tech deals content. Based in London, Millie has spent a lifetime stubbornly refusing to pay full price on any possible purchase. She has years of searching for the best discounts on the latest and greatest phones, TVs and gadgets under her belt, and knows how to sort the best deals from the rest. Helping readers save on the products they want is her mission, whether it’s an Apple Watch or a new tablet.&lt;/p&gt;&lt;p&gt;Since working at Tom’s Guide, Millie has covered retail events like Prime Day, Black Friday and Cyber Monday extensively, meaning she knows the products readers are looking for and the best times of year to hit “purchase.”&lt;/p&gt;&lt;p&gt;When she’s not looking for discounts, Millie covers news and writes how-to articles about everything from phones, streaming devices, and headphones to apps and video games.&lt;/p&gt;&lt;p&gt;In her spare time, Millie enjoys reading, gaming on her Nintendo Switch and creating digital art. She’s also a fan of watching Disney movies and collecting plush (the latter having totally taken over her bedroom.)&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/4uC9Qfgqx7zRMJSQ2qkZ7F-1920-80.jpg">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Hoka Clifton 10 sneaker held in hand]]></media:description>                                                            <media:text><![CDATA[Hoka Clifton 10 sneaker held in hand]]></media:text>
                                <media:title type="plain"><![CDATA[Hoka Clifton 10 sneaker held in hand]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/4uC9Qfgqx7zRMJSQ2qkZ7F-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Want to stay active through the fall season? A bunch of brands are offering <a href="https://www.amazon.com/Womens-Running-Shoes/b/ref=dp_bc_5?ie=UTF8&amp;node=679360011" target="_blank" rel="nofollow">fall running shoe deals, including Asics, New Balance, Brooks and more</a>.</p><p>I've searched everywhere to find the biggest discounts on the most popular shoes, so I've done all the hard work for you. Keep scrolling to check out the best running shoe deals! Whether you're looking for a comfortable max cushioned pair or want a lightweight shoe to set PRs in, there's something for everybody.</p><p><strong>Note: </strong>prices vary depending on the size and color you choose; search the different color options available in your size to find the best deals.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links </span></h3><ul><li><strong>New Balance: </strong><a href="https://www.amazon.com/stores/page/855D4CDF-ADB7-4BE8-9E26-A085D029E4B5?" target="_blank" rel="nofollow"><strong>up to 50% off</strong></a></li><li><strong>Asics: </strong><a href="https://www.amazon.com/stores/page/848769B1-4C68-4CA5-B2E7-A4480A3FBF59" target="_blank" rel="nofollow"><strong>deals from $54</strong></a></li><li><strong>Adidas: </strong><a href="https://www.amazon.com/stores/adidas/page/5E398A61-45C7-46F9-A6C6-5B4797CC5063?" target="_blank" rel="nofollow"><strong>deals from $39</strong></a></li><li><strong>Brooks: </strong><a href="https://www.amazon.com/stores/Brooks/page/B6834DFA-396F-4E38-98F6-3D2739393271?" target="_blank" rel="nofollow"><strong>up to 40% off</strong></a></li><li><strong>Hoka: </strong><a href="https://www.hoka.com/en/us/sale/" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li><li><strong>Nike: </strong><a href="https://www.amazon.com/stores/page/E9C7C6A6-9A88-4959-A67F-4D44FC67320F" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li></ul><h3 class="article-body__section" id="section-best-new-balance-deals"><span>Best New Balance Deals</span></h3><div class="product"><a data-dimension112="c2df5748-d2c0-11f1-abac-87b33ee2717a" data-action="Deal Block" data-label="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension48="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension25="$108" href="https://www.amazon.com/New-Balance-FuelCell-Running-Afterglow/dp/B0F4LLKZCH" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:880px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="zMXtGm9YKG3arrNYXpTBH" name="New Balance Rebel v5 sq" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zMXtGm9YKG3arrNYXpTBH-1920-80.jpg" mos="" align="middle" fullscreen="" width="880" height="880" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-FuelCell-Running-Afterglow/dp/B0F4LLKZCH" target="_blank" rel="nofollow" data-dimension112="c2df5748-d2c0-11f1-abac-87b33ee2717a" data-action="Deal Block" data-label="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension48="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension25="$108">FuelCell Rebel v5 Running Shoes (Women's): was $144 now $108</a></strong><br />The lightweight <a href="https://www.tomsguide.com/wellness/running/new-balance-rebel-v5-review">New Balance FuelCell Rebel v5</a> is a comfortable and speedy daily trainer that's perfect for those who don't love the feel of max-cushioned shoes, as it has a more grounded feel.<a class="view-deal button" href="https://www.amazon.com/New-Balance-FuelCell-Running-Afterglow/dp/B0F4LLKZCH" target="_blank" rel="nofollow" data-dimension112="c2df5748-d2c0-11f1-abac-87b33ee2717a" data-action="Deal Block" data-label="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension48="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension25="$108">View Deal</a></p></div><div class="product"><a data-dimension112="c2df57ac-d2c0-11f1-9922-b5bc8ba20a25" data-action="Deal Block" data-label="Fresh Foam X Hierro v9 (Women's)" data-dimension48="Fresh Foam X Hierro v9 (Women's)" data-dimension25="$123" href="https://www.amazon.com/New-Balance-Womens-Running-Afterglow/dp/B0F4LHFJZH" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:825px;"><p class="vanilla-image-block" style="padding-top:60.00%;"><img id="rKNw53FMMtAELn6kVTTGxk" name="New Balance Fresh Foam X Hierro v9" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/rKNw53FMMtAELn6kVTTGxk-1920-80.png" mos="" align="middle" fullscreen="" width="825" height="495" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-Womens-Running-Afterglow/dp/B0F4LHFJZH" target="_blank" rel="nofollow" data-dimension112="c2df57ac-d2c0-11f1-9922-b5bc8ba20a25" data-action="Deal Block" data-label="Fresh Foam X Hierro v9 (Women's)" data-dimension48="Fresh Foam X Hierro v9 (Women's)" data-dimension25="$123">Fresh Foam X Hierro v9 (Women's): was $159 now $123</a></strong><br />The <a href="https://www.tomsguide.com/wellness/running/new-balance-fresh-foam-x-hierro-v9-review">New Balance Fresh Foam X Hierro v9</a> is a comfortable trail-running and hiking shoe that’s great for active trips. Despite its plush feel, it's still nice and stable with solid grip. You probably won't set your fastest times in this shoe, but it feels great to run in.<a class="view-deal button" href="https://www.amazon.com/New-Balance-Womens-Running-Afterglow/dp/B0F4LHFJZH" target="_blank" rel="nofollow" data-dimension112="c2df57ac-d2c0-11f1-9922-b5bc8ba20a25" data-action="Deal Block" data-label="Fresh Foam X Hierro v9 (Women's)" data-dimension48="Fresh Foam X Hierro v9 (Women's)" data-dimension25="$123">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5810-d2c0-11f1-b235-7d0176f3f2d7" data-action="Deal Block" data-label="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension48="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension25="$144" href="https://www.amazon.com/New-Balance-Running-Metallic-Inkwell/dp/B0CLB6X87W" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:880px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="XwbzzRSwcghwdApXRMQfb5" name="New Balance 1080v14 sq" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XwbzzRSwcghwdApXRMQfb5-1920-80.jpg" mos="" align="middle" fullscreen="" width="880" height="880" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-Running-Metallic-Inkwell/dp/B0CLB6X87W" target="_blank" rel="nofollow" data-dimension112="c2df5810-d2c0-11f1-b235-7d0176f3f2d7" data-action="Deal Block" data-label="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension48="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension25="$144">Fresh Foam X 1080v14 Running Shoe (Men's): was $164 now $144</a></strong><br />We gave this shoe a 4-star rating in our <a href="https://www.tomsguide.com/wellness/running/new-balance-fresh-foam-x-1080v14-review">New Balance Fresh Foam X 1080v14 review</a>, saying that this is a cushioned daily trainer that offers a great balance of comfort and weight.<a class="view-deal button" href="https://www.amazon.com/New-Balance-Running-Metallic-Inkwell/dp/B0CLB6X87W" target="_blank" rel="nofollow" data-dimension112="c2df5810-d2c0-11f1-b235-7d0176f3f2d7" data-action="Deal Block" data-label="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension48="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension25="$144">View Deal</a></p></div><div class="product"><a data-dimension112="c2df58a6-d2c0-11f1-ae3f-e5f6a5a0b16d" data-action="Deal Block" data-label="FuelCell Supercomp Elite V5 (Women's)" data-dimension48="FuelCell Supercomp Elite V5 (Women's)" data-dimension25="$145" href="https://www.amazon.com/New-Balance-FuelCell-SuperComp-Tangerine/dp/B0F4LZ7VDR" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1267px;"><p class="vanilla-image-block" style="padding-top:54.85%;"><img id="BXfy6JhfauCEwEyTDyxFe3" name="FuelCell Supercomp Elite V5 (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/BXfy6JhfauCEwEyTDyxFe3-1920-80.jpg" mos="" align="middle" fullscreen="" width="1267" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-FuelCell-SuperComp-Tangerine/dp/B0F4LZ7VDR" target="_blank" rel="nofollow" data-dimension112="c2df58a6-d2c0-11f1-ae3f-e5f6a5a0b16d" data-action="Deal Block" data-label="FuelCell Supercomp Elite V5 (Women's)" data-dimension48="FuelCell Supercomp Elite V5 (Women's)" data-dimension25="$145">FuelCell Supercomp Elite V5 (Women's): was $264 now $145</a></strong><br />Our Fitness Editor, Jane McGuire, ran her fastest marathon in the Supercomp Elite V5 — and our Senior Fitness Writer, Nick Harris-Fry loved their lightweight, propulsive design in his <a href="https://www.tomsguide.com/wellness/running/new-balance-sc-elite-v5-review">New Balance FuelCell Supercomp Elite V5 review</a>. Don't sleep on this saving!<a class="view-deal button" href="https://www.amazon.com/New-Balance-FuelCell-SuperComp-Tangerine/dp/B0F4LZ7VDR" target="_blank" rel="nofollow" data-dimension112="c2df58a6-d2c0-11f1-ae3f-e5f6a5a0b16d" data-action="Deal Block" data-label="FuelCell Supercomp Elite V5 (Women's)" data-dimension48="FuelCell Supercomp Elite V5 (Women's)" data-dimension25="$145">View Deal</a></p></div><h3 class="article-body__section" id="section-best-asics-deals"><span>Best Asics Deals</span></h3><div class="product"><a data-dimension112="c2df59a0-d2c0-11f1-9c7c-dbde66422e87" data-action="Deal Block" data-label="Gel-Pulse 16 (Women's)" data-dimension48="Gel-Pulse 16 (Women's)" data-dimension25="$47" href="https://www.amazon.com/ASICS-Womens-Gel-Pulse-Running-Midnight/dp/B0F63XHPW5" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:48.88%;"><img id="Woj2dkTQp2a9nuWs5nFuDg" name="Gel-Pulse 16 (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Woj2dkTQp2a9nuWs5nFuDg-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="565" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Pulse-Running-Midnight/dp/B0F63XHPW5" target="_blank" rel="nofollow" data-dimension112="c2df59a0-d2c0-11f1-9c7c-dbde66422e87" data-action="Deal Block" data-label="Gel-Pulse 16 (Women's)" data-dimension48="Gel-Pulse 16 (Women's)" data-dimension25="$47">Gel-Pulse 16 (Women's): was $100 now $47</a></strong><br />This is one of the cheapest Asics running shoe deals you'll find, so this shoe is definitely worth a purchase. However, stock is limited, so act fast! It's regarded as a comfy and versatile sneaker that suits neutral runners in particular.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Gel-Pulse-Running-Midnight/dp/B0F63XHPW5" target="_blank" rel="nofollow" data-dimension112="c2df59a0-d2c0-11f1-9c7c-dbde66422e87" data-action="Deal Block" data-label="Gel-Pulse 16 (Women's)" data-dimension48="Gel-Pulse 16 (Women's)" data-dimension25="$47">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5a0e-d2c0-11f1-bdc9-95741a9ee26f" data-action="Deal Block" data-label="Gel-Kayano 30 (Women's)" data-dimension48="Gel-Kayano 30 (Women's)" data-dimension25="$69" href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1160px;"><p class="vanilla-image-block" style="padding-top:46.29%;"><img id="iHsvdtLnzyeWEyCZV8HBYe" name="Gel-Kayano 30 (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/iHsvdtLnzyeWEyCZV8HBYe-1920-80.jpg" mos="" align="middle" fullscreen="" width="1160" height="537" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow" data-dimension112="c2df5a0e-d2c0-11f1-bdc9-95741a9ee26f" data-action="Deal Block" data-label="Gel-Kayano 30 (Women's)" data-dimension48="Gel-Kayano 30 (Women's)" data-dimension25="$69">Gel-Kayano 30 (Women's): was $160 now $69</a></strong><br />The Gel Kayano 30 running shoes are an older model, but they're amazingly cheap with 56% off. They're designed to provide advanced stability and soft cushioning for neutral runners and overpronators alike. Our Deals Editor-in-Chief, Louis Ramirez, wrote: "I've been using these shoes for almost two years now. (I loved them so much I bought a second pair months after buying my first pair). I find that they're great for casual runs on the treadmill, HIIT sessions, and long distance running outdoors."<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow" data-dimension112="c2df5a0e-d2c0-11f1-bdc9-95741a9ee26f" data-action="Deal Block" data-label="Gel-Kayano 30 (Women's)" data-dimension48="Gel-Kayano 30 (Women's)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5a72-d2c0-11f1-94eb-63c8e0f41529" data-action="Deal Block" data-label="Women's Novablast 4" data-dimension48="Women's Novablast 4" data-dimension25="$67" href="https://www.amazon.com/ASICS-Womens-NOVABLAST-Running-Expanse/dp/B0CFP3J6RB" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1200px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="wMYSVC2325TPeXMt7TJ9t3" name="Asics Novablast 4" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/wMYSVC2325TPeXMt7TJ9t3-1920-80.jpg" mos="" align="middle" fullscreen="" width="1200" height="1200" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-NOVABLAST-Running-Expanse/dp/B0CFP3J6RB" target="_blank" rel="nofollow" data-dimension112="c2df5a72-d2c0-11f1-94eb-63c8e0f41529" data-action="Deal Block" data-label="Women's Novablast 4" data-dimension48="Women's Novablast 4" data-dimension25="$67">Women's Novablast 4: was $140 now $67</a></strong><br />Old but gold. While the Novablast 6 is now available, the Novablast 4 is beloved by the Tom's Guide team — especially our Fitness Editor Jane McGuire, who wrote: "I've run over 100 miles in this shoe, and it's still one I reach for when I'm heading out for a long run."<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-NOVABLAST-Running-Expanse/dp/B0CFP3J6RB" target="_blank" rel="nofollow" data-dimension112="c2df5a72-d2c0-11f1-94eb-63c8e0f41529" data-action="Deal Block" data-label="Women's Novablast 4" data-dimension48="Women's Novablast 4" data-dimension25="$67">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5acc-d2c0-11f1-9c7a-17ad5fda44b4" data-action="Deal Block" data-label="Sonicblast Road Running Shoes (Men's)" data-dimension48="Sonicblast Road Running Shoes (Men's)" data-dimension25="$81" href="https://www.amazon.com/Asics-SONICBLAST-Running-Winter-Stillwater/dp/B0DPLQ32YV" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1528px;"><p class="vanilla-image-block" style="padding-top:75.00%;"><img id="rD9sdYvxaqtEV2BgyMfTx" name="Sonicblast" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/rD9sdYvxaqtEV2BgyMfTx-1920-80.jpg" mos="" align="middle" fullscreen="" width="1528" height="1146" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Asics-SONICBLAST-Running-Winter-Stillwater/dp/B0DPLQ32YV" target="_blank" rel="nofollow" data-dimension112="c2df5acc-d2c0-11f1-9c7a-17ad5fda44b4" data-action="Deal Block" data-label="Sonicblast Road Running Shoes (Men's)" data-dimension48="Sonicblast Road Running Shoes (Men's)" data-dimension25="$81">Sonicblast Road Running Shoes (Men's): was $180 now $81</a></strong><br />Suited for both fast runs and everyday training, the Asics Sonicblast are super lightweight and propulsive. There's an Astroplate mechanism to help you shoot forward, as well as FF Blast Max and FF Turbo cushioning for a bouncy feel underfoot.<a class="view-deal button" href="https://www.amazon.com/Asics-SONICBLAST-Running-Winter-Stillwater/dp/B0DPLQ32YV" target="_blank" rel="nofollow" data-dimension112="c2df5acc-d2c0-11f1-9c7a-17ad5fda44b4" data-action="Deal Block" data-label="Sonicblast Road Running Shoes (Men's)" data-dimension48="Sonicblast Road Running Shoes (Men's)" data-dimension25="$81">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5b30-d2c0-11f1-9150-d3d7297169c5" data-action="Deal Block" data-label="Novablast 5 (Men's)" data-dimension48="Novablast 5 (Men's)" data-dimension25="$129" href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1166px;"><p class="vanilla-image-block" style="padding-top:48.80%;"><img id="4pk4xESon4iEcQDmd7TqZF" name="Novablast 5 (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4pk4xESon4iEcQDmd7TqZF-1920-80.jpg" mos="" align="middle" fullscreen="" width="1166" height="569" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow" data-dimension112="c2df5b30-d2c0-11f1-9150-d3d7297169c5" data-action="Deal Block" data-label="Novablast 5 (Men's)" data-dimension48="Novablast 5 (Men's)" data-dimension25="$129">Novablast 5 (Men's): was $160 now $129</a></strong><br />We voted the Asics Novablast 6 as the <a href="https://www.tomsguide.com/best-picks/best-running-shoes">best running shoes</a> you can buy right now, but before that, the <a href="https://www.tomsguide.com/wellness/running/asics-novablast-5-review">Asics Novablast 5</a> had the top spot. They quickly stood out for their balance of comfort, support and fun, making them a pair of shoes you will actually look forward to running in. They're lightweight, durable and have a soft, springy feel underfoot that helps absorb impact while keeping runs enjoyable.<a class="view-deal button" href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow" data-dimension112="c2df5b30-d2c0-11f1-9150-d3d7297169c5" data-action="Deal Block" data-label="Novablast 5 (Men's)" data-dimension48="Novablast 5 (Men's)" data-dimension25="$129">View Deal</a></p></div><h3 class="article-body__section" id="section-best-nike-deals"><span>Best Nike Deals</span></h3><div class="product"><a data-dimension112="c2df5bee-d2c0-11f1-aff0-45b8bc229328" data-action="Deal Block" data-label="Pegasus 42 (Men's)" data-dimension48="Pegasus 42 (Men's)" data-dimension25="$82" href="https://www.nike.com/t/pegasus-42-mens-road-running-shoes-S1bYkOza/IB1873-107" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1070px;"><p class="vanilla-image-block" style="padding-top:125.05%;"><img id="uxG2rhW9L4NBaWbeVEreNS" name="Nike Pegasus 42" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/uxG2rhW9L4NBaWbeVEreNS-1920-80.png" mos="" align="middle" fullscreen="" width="1070" height="1338" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nike.com/t/pegasus-42-mens-road-running-shoes-S1bYkOza/IB1873-107" target="_blank" rel="nofollow" data-dimension112="c2df5bee-d2c0-11f1-aff0-45b8bc229328" data-action="Deal Block" data-label="Pegasus 42 (Men's)" data-dimension48="Pegasus 42 (Men's)" data-dimension25="$82">Pegasus 42 (Men's): was $145 now $82</a></strong><br />Earning a 3.5-star rating in our <a href="https://www.tomsguide.com/wellness/running/nike-pegasus-42-review">Nike Pegasus 42 review</a>, we currently rank this as one of the <a href="https://www.tomsguide.com/best-picks/best-running-shoes">best running shoes</a> you can buy in terms of value. Compared to the Pegasus 41 (which was already great,) the 42 feels even smoother and more energetic underfoot. It's a great shoe for just about anybody.<a class="view-deal button" href="https://www.nike.com/t/pegasus-42-mens-road-running-shoes-S1bYkOza/IB1873-107" target="_blank" rel="nofollow" data-dimension112="c2df5bee-d2c0-11f1-aff0-45b8bc229328" data-action="Deal Block" data-label="Pegasus 42 (Men's)" data-dimension48="Pegasus 42 (Men's)" data-dimension25="$82">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5c52-d2c0-11f1-a82a-ad821506e16a" data-action="Deal Block" data-label="Vomero 18 Running Shoes (Women's)" data-dimension48="Vomero 18 Running Shoes (Women's)" data-dimension25="$116" href="https://www.amazon.com/dp/B0FRNJB2NY" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:44.46%;"><img id="on8DUvsokY6RbJszwfXseQ" name="Vomero" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/on8DUvsokY6RbJszwfXseQ-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="309" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0FRNJB2NY" target="_blank" rel="nofollow" data-dimension112="c2df5c52-d2c0-11f1-a82a-ad821506e16a" data-action="Deal Block" data-label="Vomero 18 Running Shoes (Women's)" data-dimension48="Vomero 18 Running Shoes (Women's)" data-dimension25="$116">Vomero 18 Running Shoes (Women's): was $155 now $116</a></strong><br />The <a href="https://www.tomsguide.com/wellness/running/nike-vomero-18-review">Nike Vomero 18</a> is a max-cushioned cruiser that's ideal for protecting the body on long and easy runs. It's plush, comfortable and stable. The shoe is pretty heavy, but if you're looking for plush, sink-in comfort, this one ticks that box. <a class="view-deal button" href="https://www.amazon.com/dp/B0FRNJB2NY" target="_blank" rel="nofollow" data-dimension112="c2df5c52-d2c0-11f1-a82a-ad821506e16a" data-action="Deal Block" data-label="Vomero 18 Running Shoes (Women's)" data-dimension48="Vomero 18 Running Shoes (Women's)" data-dimension25="$116">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5cb6-d2c0-11f1-9f82-455a1192f058" data-action="Deal Block" data-label="Vomero Plus (Men's)" data-dimension48="Vomero Plus (Men's)" data-dimension25="$152" href="https://www.nike.com/t/vomero-plus-mens-road-running-shoes-5npsVBwT/HV8150-111" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1070px;"><p class="vanilla-image-block" style="padding-top:125.05%;"><img id="ee4dBpGa8AkgSBMVwAnYhb" name="Vomero Plus (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ee4dBpGa8AkgSBMVwAnYhb-1920-80.jpg" mos="" align="middle" fullscreen="" width="1070" height="1338" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nike.com/t/vomero-plus-mens-road-running-shoes-5npsVBwT/HV8150-111" target="_blank" rel="nofollow" data-dimension112="c2df5cb6-d2c0-11f1-9f82-455a1192f058" data-action="Deal Block" data-label="Vomero Plus (Men's)" data-dimension48="Vomero Plus (Men's)" data-dimension25="$152">Vomero Plus (Men's): was $180 now $152</a></strong><br />The <a href="https://www.tomsguide.com/wellness/running/i-ran-50-miles-in-the-nike-vomero-plus-and-its-my-new-favorite-running-shoe">Nike Vomero Plus</a> offers an unrivalled level of bounce and fun thanks to its springy ZoomX midsole. It makes easy and long runs all the more enjoyable in particular. The biggest drawback is the fact it costs $180 at full price, but that’s no longer a problem because the Vomero Plus is reduced right now.<a class="view-deal button" href="https://www.nike.com/t/vomero-plus-mens-road-running-shoes-5npsVBwT/HV8150-111" target="_blank" rel="nofollow" data-dimension112="c2df5cb6-d2c0-11f1-9f82-455a1192f058" data-action="Deal Block" data-label="Vomero Plus (Men's)" data-dimension48="Vomero Plus (Men's)" data-dimension25="$152">View Deal</a></p></div><h3 class="article-body__section" id="section-best-hoka-deals"><span>Best Hoka Deals</span></h3><div class="product"><a data-dimension112="c2df5d74-d2c0-11f1-8d42-c9caeb93b15c" data-action="Deal Block" data-label="Arahi 8 (Women's)" data-dimension48="Arahi 8 (Women's)" data-dimension25="$120" href="https://www.hoka.com/en/us/womens-everyday-running-shoes/arahi-8/1168691.html?dwvar_1168691_color=FSTS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1932px;"><p class="vanilla-image-block" style="padding-top:81.11%;"><img id="EUf3iisgBNqSoAfRcsnYMU" name="Arahi 8" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/EUf3iisgBNqSoAfRcsnYMU-1920-80.jpg" mos="" align="middle" fullscreen="" width="1932" height="1567" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/womens-everyday-running-shoes/arahi-8/1168691.html?dwvar_1168691_color=FSTS" target="_blank" rel="nofollow" data-dimension112="c2df5d74-d2c0-11f1-8d42-c9caeb93b15c" data-action="Deal Block" data-label="Arahi 8 (Women's)" data-dimension48="Arahi 8 (Women's)" data-dimension25="$120">Arahi 8 (Women's): was $150 now $120</a></strong><br />The Arahi 8 is the stable counterpart to the Clifton 10, offering extra support for runners who overpronate along with Hoka's familiar smooth, cushioned ride. It'd great for neutral runners, and the newer Arahi 9 is very similar in all respects, so the older model is definitely better value in the sale.<a class="view-deal button" href="https://www.hoka.com/en/us/womens-everyday-running-shoes/arahi-8/1168691.html?dwvar_1168691_color=FSTS" target="_blank" rel="nofollow" data-dimension112="c2df5d74-d2c0-11f1-8d42-c9caeb93b15c" data-action="Deal Block" data-label="Arahi 8 (Women's)" data-dimension48="Arahi 8 (Women's)" data-dimension25="$120">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5dd8-d2c0-11f1-9f4e-1192ecbad4b4" data-action="Deal Block" data-label="Clifton 10 (Men's)" data-dimension48="Clifton 10 (Men's)" data-dimension25="$124" href="https://www.hoka.com/en/us/mens-everyday-running-gear/clifton-10/1162030.html?dwvar_1162030_color=WKY" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1932px;"><p class="vanilla-image-block" style="padding-top:81.11%;"><img id="pTkmatx4tcURfCFTcWdCu9" name="Clifton 10" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pTkmatx4tcURfCFTcWdCu9-1920-80.jpg" mos="" align="middle" fullscreen="" width="1932" height="1567" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/mens-everyday-running-gear/clifton-10/1162030.html?dwvar_1162030_color=WKY" target="_blank" rel="nofollow" data-dimension112="c2df5dd8-d2c0-11f1-9f4e-1192ecbad4b4" data-action="Deal Block" data-label="Clifton 10 (Men's)" data-dimension48="Clifton 10 (Men's)" data-dimension25="$124">Clifton 10 (Men's): was $155 now $124</a></strong><br />The Clifton is the most popular Hoka running shoe for a reason. It’s the perfect place to start with the brand, offering a smooth, comfortable ride that will suit runners of all levels well. It also offers better value than Hoka's rivals, like the Bondi 9.<a class="view-deal button" href="https://www.hoka.com/en/us/mens-everyday-running-gear/clifton-10/1162030.html?dwvar_1162030_color=WKY" target="_blank" rel="nofollow" data-dimension112="c2df5dd8-d2c0-11f1-9f4e-1192ecbad4b4" data-action="Deal Block" data-label="Clifton 10 (Men's)" data-dimension48="Clifton 10 (Men's)" data-dimension25="$124">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5e32-d2c0-11f1-ab60-7707c7d9918d" data-action="Deal Block" data-label="Clifton 9 GTX (Women's)" data-dimension48="Clifton 9 GTX (Women's)" data-dimension25="$132" href="https://www.hoka.com/en/us/womens-everyday-running-shoes/clifton-9-gtx/1141490.html?dwvar_1141490_color=BNDR" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1932px;"><p class="vanilla-image-block" style="padding-top:81.11%;"><img id="RRxC8fKVUmNBdxEfjnVQFf" name="Clifton 9 GTX (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/RRxC8fKVUmNBdxEfjnVQFf-1920-80.webp" mos="" align="middle" fullscreen="" width="1932" height="1567" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/womens-everyday-running-shoes/clifton-9-gtx/1141490.html?dwvar_1141490_color=BNDR" target="_blank" rel="nofollow" data-dimension112="c2df5e32-d2c0-11f1-ab60-7707c7d9918d" data-action="Deal Block" data-label="Clifton 9 GTX (Women's)" data-dimension48="Clifton 9 GTX (Women's)" data-dimension25="$132">Clifton 9 GTX (Women's): was $165 now $132</a></strong><br />The <a href="https://www.tomsguide.com/reviews/hoka-clifton-9">Hoka Clifton 9</a> is a cushioned, everyday running shoe that’ll work well for beginners and more experienced runners alike. It’s not the fanciest or the fastest shoe around, but it’s reliably comfortable, whether you’re training for a marathon or using this shoe for your walking workouts. The GTX version adds weatherproofing, so you'll get more out of your walks and runs, rain or shine.<a class="view-deal button" href="https://www.hoka.com/en/us/womens-everyday-running-shoes/clifton-9-gtx/1141490.html?dwvar_1141490_color=BNDR" target="_blank" rel="nofollow" data-dimension112="c2df5e32-d2c0-11f1-ab60-7707c7d9918d" data-action="Deal Block" data-label="Clifton 9 GTX (Women's)" data-dimension48="Clifton 9 GTX (Women's)" data-dimension25="$132">View Deal</a></p></div><h3 class="article-body__section" id="section-best-brooks-deals"><span>Best Brooks Deals</span></h3><div class="product"><a data-dimension112="c2df5ef0-d2c0-11f1-9329-334fc9bf762d" data-action="Deal Block" data-label="Hyperion" data-dimension48="Hyperion" data-dimension25="$72" href="https://www.amazon.com/Brooks-Mens-Hyperion-Neutral-Running/dp/B0BMT316TB?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1035px;"><p class="vanilla-image-block" style="padding-top:67.15%;"><img id="crYpUdxjpNUYpBCknBJzHX" name="Brooks Hyperion" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/crYpUdxjpNUYpBCknBJzHX-1920-80.jpg" mos="" align="middle" fullscreen="" width="1035" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Brooks-Mens-Hyperion-Neutral-Running/dp/B0BMT316TB?" target="_blank" rel="nofollow" data-dimension112="c2df5ef0-d2c0-11f1-9329-334fc9bf762d" data-action="Deal Block" data-label="Hyperion" data-dimension48="Hyperion" data-dimension25="$72">Hyperion: was $140 now $72</a></strong><br />With prices starting from $72, this is one of the more affordable Brooks shoes you'll find. They're designed to be lightweight, speedy and to help you navigate transitions with ease.<a class="view-deal button" href="https://www.amazon.com/Brooks-Mens-Hyperion-Neutral-Running/dp/B0BMT316TB?" target="_blank" rel="nofollow" data-dimension112="c2df5ef0-d2c0-11f1-9329-334fc9bf762d" data-action="Deal Block" data-label="Hyperion" data-dimension48="Hyperion" data-dimension25="$72">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5f54-d2c0-11f1-aeb0-e710137431e9" data-action="Deal Block" data-label="Hyperion Max 3 (Men's)" data-dimension48="Hyperion Max 3 (Men's)" data-dimension25="$108" href="https://www.amazon.com/dp/B0DM3MTXGK?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:840px;"><p class="vanilla-image-block" style="padding-top:68.45%;"><img id="bf7gzstL3kTG3roVNuaN4L" name="Brooks Hyperion Max" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bf7gzstL3kTG3roVNuaN4L-1920-80.png" mos="" align="middle" fullscreen="" width="840" height="575" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0DM3MTXGK?" target="_blank" rel="nofollow" data-dimension112="c2df5f54-d2c0-11f1-aeb0-e710137431e9" data-action="Deal Block" data-label="Hyperion Max 3 (Men's)" data-dimension48="Hyperion Max 3 (Men's)" data-dimension25="$108">Hyperion Max 3 (Men's): was $199 now $108</a></strong><br />The Brooks Hyperion Max 3 is a plated training shoe with a mega-stack of cushioning in its midsole, the top layer of which is made from a particularly springy PEBA material. It's a speedier option than shoes like the Glycerin and Ghost, and still comfortable for easy runs as well.<a class="view-deal button" href="https://www.amazon.com/dp/B0DM3MTXGK?" target="_blank" rel="nofollow" data-dimension112="c2df5f54-d2c0-11f1-aeb0-e710137431e9" data-action="Deal Block" data-label="Hyperion Max 3 (Men's)" data-dimension48="Hyperion Max 3 (Men's)" data-dimension25="$108">View Deal</a></p></div><div class="product"><a data-dimension112="c2df5fcc-d2c0-11f1-9639-7d5af08a33f8" data-action="Deal Block" data-label="Ghost Max 3 (Men's)" data-dimension48="Ghost Max 3 (Men's)" data-dimension25="$109" href="https://www.amazon.com/dp/B0DM3R7VD1?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:890px;"><p class="vanilla-image-block" style="padding-top:64.61%;"><img id="mL6eZbPdx2NmSyzvQSMAcc" name="Brooks Ghost Max 3" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/mL6eZbPdx2NmSyzvQSMAcc-1920-80.png" mos="" align="middle" fullscreen="" width="890" height="575" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0DM3R7VD1?" target="_blank" rel="nofollow" data-dimension112="c2df5fcc-d2c0-11f1-9639-7d5af08a33f8" data-action="Deal Block" data-label="Ghost Max 3 (Men's)" data-dimension48="Ghost Max 3 (Men's)" data-dimension25="$109">Ghost Max 3 (Men's): was $159 now $109</a></strong><br />The Ghost Max 3 is a more cushioned and rockered alternative to the Ghost 17. The Ghost Max 4 has just come out, meaning the Ghost Max 3 is reduced by $50, with plenty of colors and sizes included in the sale.<a class="view-deal button" href="https://www.amazon.com/dp/B0DM3R7VD1?" target="_blank" rel="nofollow" data-dimension112="c2df5fcc-d2c0-11f1-9639-7d5af08a33f8" data-action="Deal Block" data-label="Ghost Max 3 (Men's)" data-dimension48="Ghost Max 3 (Men's)" data-dimension25="$109">View Deal</a></p></div><div class="product"><a data-dimension112="c2df60a8-d2c0-11f1-8324-df0cbc45e6cc" data-action="Deal Block" data-label="Glycerin Max (Women's)" data-dimension48="Glycerin Max (Women's)" data-dimension25="$149" href="https://www.amazon.com/Brooks-Womens-Glycerin-Peacoat-Ribbon/dp/B0D3B6HXJ7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:926px;"><p class="vanilla-image-block" style="padding-top:62.10%;"><img id="Y98AvyBg8eBD4Re2iRNXC6" name="Brooks Gycerin Max" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Y98AvyBg8eBD4Re2iRNXC6-1920-80.png" mos="" align="middle" fullscreen="" width="926" height="575" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Brooks-Womens-Glycerin-Peacoat-Ribbon/dp/B0D3B6HXJ7" target="_blank" rel="nofollow" data-dimension112="c2df60a8-d2c0-11f1-8324-df0cbc45e6cc" data-action="Deal Block" data-label="Glycerin Max (Women's)" data-dimension48="Glycerin Max (Women's)" data-dimension25="$149">Glycerin Max (Women's): was $199 now $149</a></strong><br />The original Glycerin Max is not just $50 cheaper than the Glycerin Max 2 thanks to this deal, but it's arguably better than the latest model because it's a bit lighter. This is the most cushioned model in the Brooks' line-up, and perfect for anyone who loves a comfortable running shoe.<a class="view-deal button" href="https://www.amazon.com/Brooks-Womens-Glycerin-Peacoat-Ribbon/dp/B0D3B6HXJ7" target="_blank" rel="nofollow" data-dimension112="c2df60a8-d2c0-11f1-8324-df0cbc45e6cc" data-action="Deal Block" data-label="Glycerin Max (Women's)" data-dimension48="Glycerin Max (Women's)" data-dimension25="$149">View Deal</a></p></div><div class="product"><a data-dimension112="c2df6120-d2c0-11f1-a95b-63a369414996" data-action="Deal Block" data-label="Hyperion Elite 5" data-dimension48="Hyperion Elite 5" data-dimension25="$149" href="https://www.amazon.com/dp/B0F4NG15WR?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:980px;"><p class="vanilla-image-block" style="padding-top:58.67%;"><img id="ZsxwPp8UrjYaq3Tu7V3wud" name="Brooks Hyperion Elite 5" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZsxwPp8UrjYaq3Tu7V3wud-1920-80.png" mos="" align="middle" fullscreen="" width="980" height="575" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>When it comes to running fast, carbon plate racers are the shoe to go for, but they're normally prohibitively expensive. Thanks to this $75 saving the Brooks Hyperion Elite 5 is under $200 in the Amazon sale. It's still not exactly cheap, but if you have PRs in mind, it will help get you there with its lightweight, propulsive design.<a class="view-deal button" href="https://www.amazon.com/dp/B0F4NG15WR?" target="_blank" rel="nofollow" data-dimension112="c2df6120-d2c0-11f1-a95b-63a369414996" data-action="Deal Block" data-label="Hyperion Elite 5" data-dimension48="Hyperion Elite 5" data-dimension25="$149">View Deal</a></p></div><h3 class="article-body__section" id="section-best-saucony-deals"><span>Best Saucony Deals</span></h3><div class="product"><a data-dimension112="c2df61e8-d2c0-11f1-9967-bb277f443bb4" data-action="Deal Block" data-label="Cohesion 14 Shoes (Women's)" data-dimension48="Cohesion 14 Shoes (Women's)" data-dimension25="$50" href="https://www.amazon.com/dp/B08CGR4YKG?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:58.99%;"><img id="pdjLV6pX6UWTGkcfsqaSE3" name="Cohesion 14 Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pdjLV6pX6UWTGkcfsqaSE3-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="410" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B08CGR4YKG?" target="_blank" rel="nofollow" data-dimension112="c2df61e8-d2c0-11f1-9967-bb277f443bb4" data-action="Deal Block" data-label="Cohesion 14 Shoes (Women's)" data-dimension48="Cohesion 14 Shoes (Women's)" data-dimension25="$50">Cohesion 14 Shoes (Women's): was $80 now $50</a></strong><br />The Saucony Cohesion 14 were already budget-friendly at $80, but now you can get a pair for even less. Shoppers on Amazon love these shoes for their comfortable and supportive design, earning these a 4.1-star rating.<a class="view-deal button" href="https://www.amazon.com/dp/B08CGR4YKG?" target="_blank" rel="nofollow" data-dimension112="c2df61e8-d2c0-11f1-9967-bb277f443bb4" data-action="Deal Block" data-label="Cohesion 14 Shoes (Women's)" data-dimension48="Cohesion 14 Shoes (Women's)" data-dimension25="$50">View Deal</a></p></div><div class="product"><a data-dimension112="c2df624c-d2c0-11f1-b2ec-11e535a9e1c3" data-action="Deal Block" data-label="Tide 2 Trainer (Men's)" data-dimension48="Tide 2 Trainer (Men's)" data-dimension25="$56" href="https://www.amazon.com/dp/B0D31XXWHZ?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1200px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="gPCzUDufYEii6Von4ywQm" name="image" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gPCzUDufYEii6Von4ywQm-1920-80.png" mos="" align="middle" fullscreen="" width="1200" height="1200" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0D31XXWHZ?" target="_blank" rel="nofollow" data-dimension112="c2df624c-d2c0-11f1-b2ec-11e535a9e1c3" data-action="Deal Block" data-label="Tide 2 Trainer (Men's)" data-dimension48="Tide 2 Trainer (Men's)" data-dimension25="$56">Tide 2 Trainer (Men's): was $100 now $56</a></strong><br />The Tide 2 is all about comfort for your everyday. It has soft, springy foam to make every step feel cushioned, a flexible plate to give you a little bounce and move with ease, <em>and</em> a breathable mesh upper to keep your feet cool. Basically, it’s perfect for walking, running errands, or just being on your feet all day without feeling sore.<a class="view-deal button" href="https://www.amazon.com/dp/B0D31XXWHZ?" target="_blank" rel="nofollow" data-dimension112="c2df624c-d2c0-11f1-b2ec-11e535a9e1c3" data-action="Deal Block" data-label="Tide 2 Trainer (Men's)" data-dimension48="Tide 2 Trainer (Men's)" data-dimension25="$56">View Deal</a></p></div><div class="product star-deal"><a data-dimension112="c2df62b0-d2c0-11f1-b672-abfae88a3776" data-action="Star Deal Block" data-label="Hurricane 24 (Men's)" data-dimension48="Hurricane 24 (Men's)" data-dimension25="$70" href="https://www.amazon.com/Saucony-Hurricane-Sneaker-Black-Shadow/dp/B0D31XQL4H" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1498px;"><p class="vanilla-image-block" style="padding-top:46.40%;"><img id="vxf7UD5T2Am7guVzFoFcZ4" name="Saucony Hurricane 24 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4-1920-80.jpg" mos="" align="middle" fullscreen="" width="1498" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Saucony-Hurricane-Sneaker-Black-Shadow/dp/B0D31XQL4H" target="_blank" rel="nofollow" data-dimension112="c2df62b0-d2c0-11f1-b672-abfae88a3776" data-action="Star Deal Block" data-label="Hurricane 24 (Men's)" data-dimension48="Hurricane 24 (Men's)" data-dimension25="$70">Hurricane 24 (Men's): was $80 now $70</a></strong><br />Running with the <a href="https://www.tomsguide.com/wellness/running/saucony-hurricane-24-review">Saucony Hurricane 24 </a>is like running on clouds. They use PWRRUN+ foam, which cushions your feet while still feeling springy. With a wide base and rocker design, it offers a stable and comfortable ride for longer or easy runs. The breathable mesh upper fits securely without being tight. The Hurricane 25 have replaced these shoes, but the 24 are the real bargain. <a class="view-deal button" href="https://www.amazon.com/Saucony-Hurricane-Sneaker-Black-Shadow/dp/B0D31XQL4H" target="_blank" rel="nofollow" data-dimension112="c2df62b0-d2c0-11f1-b672-abfae88a3776" data-action="Star Deal Block" data-label="Hurricane 24 (Men's)" data-dimension48="Hurricane 24 (Men's)" data-dimension25="$70">View Deal</a></p></div><div class="product"><a data-dimension112="c2df630a-d2c0-11f1-a069-8de46a5c3eea" data-action="Deal Block" data-label="Ride 18 (Men's)" data-dimension48="Ride 18 (Men's)" data-dimension25="$79" href="https://www.amazon.com/Saucony-Mens-Sneaker-BLACK-WHITE/dp/B0D31WZWT8" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1542px;"><p class="vanilla-image-block" style="padding-top:45.07%;"><img id="NmXRUrbSqDWhK8xTzQF7bf" name="Ride 18 (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/NmXRUrbSqDWhK8xTzQF7bf-1920-80.jpg" mos="" align="middle" fullscreen="" width="1542" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Saucony-Mens-Sneaker-BLACK-WHITE/dp/B0D31WZWT8" target="_blank" rel="nofollow" data-dimension112="c2df630a-d2c0-11f1-a069-8de46a5c3eea" data-action="Deal Block" data-label="Ride 18 (Men's)" data-dimension48="Ride 18 (Men's)" data-dimension25="$79">Ride 18 (Men's): was $145 now $79</a></strong><br />Comfort and support matter, and the <a href="https://www.tomsguide.com/wellness/fitness/i-ran-45-miles-in-the-saucony-ride-18-heres-my-verdict">Saucony Ride 18</a> delivers both. The soft, bouncy PWRRUN Plus foam feels light underfoot, helping to take the pressure off your joints as you build confidence. The stretchy mesh upper moves with your foot while the padded heel reduces rubbing that can cut runs short. Whether you’re lacing up for your first 5K or logging serious mileage, this shoe is a reliable all-rounder.<a class="view-deal button" href="https://www.amazon.com/Saucony-Mens-Sneaker-BLACK-WHITE/dp/B0D31WZWT8" target="_blank" rel="nofollow" data-dimension112="c2df630a-d2c0-11f1-a069-8de46a5c3eea" data-action="Deal Block" data-label="Ride 18 (Men's)" data-dimension48="Ride 18 (Men's)" data-dimension25="$79">View Deal</a></p></div><div class="product"><a data-dimension112="c2df636e-d2c0-11f1-a01a-f354a1da8b48" data-action="Deal Block" data-label="Triumph 23" data-dimension48="Triumph 23" data-dimension25="$89" href="https://www.amazon.com/Saucony-Triumph-Sneaker-Black-White/dp/B0DJWN776G" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="99qpJaU9RKTQSkGAmdZPrJ" name="saucony-mens-triumph-23-sneaker-whiteazu-4c83ebb7-41ff-452b-aa7e-9fe244156c64.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/99qpJaU9RKTQSkGAmdZPrJ-1920-80.jpg" mos="" align="middle" fullscreen="" width="500" height="500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Saucony Triumph 23 has a couple of key features to recommend it. One is that it's very comfortable and protective, and the other is its durability. That said, it's now discounted by 48%. It's also a lot cheaper than the <a href="https://www.tomsguide.com/wellness/running/i-ran-40-miles-in-the-saucony-triumph-24-and-its-a-return-to-form-for-the-popular-cushioned-running-shoe" data-dimension112="c2df636e-d2c0-11f1-a01a-f354a1da8b48" data-action="Deal Block" data-label="Triumph 23" data-dimension48="Triumph 23" data-dimension25="$89">Triumph 24</a>.<a class="view-deal button" href="https://www.amazon.com/Saucony-Triumph-Sneaker-Black-White/dp/B0DJWN776G" target="_blank" rel="nofollow" data-dimension112="c2df636e-d2c0-11f1-a01a-f354a1da8b48" data-action="Deal Block" data-label="Triumph 23" data-dimension48="Triumph 23" data-dimension25="$89">View Deal</a></p></div><h3 class="article-body__section" id="section-shop-more-deals"><span>Shop More Deals</span></h3><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Sneakers%2C+running+shoes%2C+sandals&amp;brands=Hoka%2CSkechers%2CAsics&amp;view_mode=carousel&amp;widget_title=Top+Deals+Handpicked+by+Our+Editors&amp;widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&amp;bg_color=light_blue" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters {      display: flex;      gap: 12px;      justify-content: center;      flex-wrap: wrap;    }    .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);      display: -webkit-box;      -webkit-line-clamp: 2;      -webkit-box-orient: vertical;      overflow: hidden;    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    .tg-df-container .tg-df-card-cta.tg-df-cta-savings-squad {      background-color: #3c8d0d;    }    .tg-df-card:hover .tg-df-card-cta.tg-df-cta-savings-squad,    .tg-df-card-cta.tg-df-cta-savings-squad:hover {      background-color: #2b6509;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 0;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 0 16px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }            .tg-df-filters {        width: calc(100% + 32px);        margin: 0 -16px;        padding: 0 16px 4px 16px;        display: flex;        justify-content: flex-start;        gap: 8px;        flex-wrap: nowrap;        overflow-x: auto;        -webkit-overflow-scrolling: touch;        scrollbar-width: none;      }      .tg-df-filters::after {        content: "";        display: block;        flex: 0 0 8px;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }            .tg-df-sort-wrapper {        flex: 0 0 max(42%, 130px);        min-width: 0;      }      .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;        -webkit-line-clamp: 3;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        -webkit-line-clamp: 3;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 16px;      text-align: center;      width: 100%;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: #f8fafc;      border-color: #cbd5e1;    }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right {      background-color: rgba(255, 255, 255, 0.4);      border: none;      box-shadow: none;      backdrop-filter: blur(4px);      -webkit-backdrop-filter: blur(4px);    }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right { right: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-right { right: 0; }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left:hover,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);      border: none;    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-carousel-roundels::after {      content: "";      flex: 0 0 32px;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;      transition: font-weight 0.2s;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-label {      font-weight: 700;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;      display: inline-flex;      align-items: center;      justify-content: center;      min-height: 36px;      box-sizing: border-box;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::after {      content: "";      flex: 0 0 32px;    }    .tg-df-grid-wrapper {      position: relative;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card {      flex: 0 0 auto;      width: 100px;      border-radius: 15px;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      border: 2px solid #1e293b;      background: white;      color: #1e293b;      display: flex;      flex-direction: column;      justify-content: center;      align-items: center;      font-weight: 600;      font-size: 14px;      cursor: pointer;      padding: 16px;      text-align: center;      transition: all 0.2s;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card:hover {      background: #1e293b;      color: white;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      -webkit-line-clamp: 2;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {      -webkit-line-clamp: 3;    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.45);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #5aaf0b; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #4a9109; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>          \x3C/div>          \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">      \x3Cdiv class="tg-df-top-bar">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>                \x3Cdiv class="tg-df-settings-wrapper">          \x3Cbutton type="button" class="tg-df-settings-btn" aria-label="Settings" id="tg-df-settings-toggle">            \x3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20">                \x3Cpath d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.73 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .43-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.49-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/>            \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-settings-dropdown-backdrop" id="tg-df-settings-backdrop">\x3C/div>          \x3Cdiv class="tg-df-settings-dropdown" id="tg-df-settings-panel">            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Search Region\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-region-select">                \x3Coption value="auto">🌍 Auto-detect\x3C/option>                \x3Coption value="US">🇺🇸 United States (US)\x3C/option>                \x3Coption value="GB">🇬🇧 United Kingdom (UK)\x3C/option>                \x3Coption value="CA">🇨🇦 Canada (CA)\x3C/option>                \x3Coption value="AU">🇦🇺 Australia (AU)\x3C/option>                \x3Coption value="DE">🇩🇪 Germany (DE)\x3C/option>                \x3Coption value="FR">🇫🇷 France (FR)\x3C/option>                \x3Coption value="IT">🇮🇹 Italy (IT)\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Retailer\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-retailer-select">                \x3Coption value="">All Retailers\x3C/option>                \x3Coption value="Amazon">Amazon\x3C/option>                \x3Coption value="Walmart">Walmart\x3C/option>                \x3Coption value="Best Buy">Best Buy\x3C/option>                \x3Coption value="Target">Target\x3C/option>                \x3Coption value="John Lewis">John Lewis\x3C/option>                \x3Coption value="Currys">Currys\x3C/option>                \x3Coption value="Argos">Argos\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Offer Type\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-offer-type-select">                \x3Coption value="">All Offers\x3C/option>                \x3Coption value="amazon_prime">Amazon Prime\x3C/option>                \x3Coption value="recommended_promo">Recommended Promo\x3C/option>                \x3Coption value="amazon_lightning">Amazon Lightning Deal\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Result Count\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-rows-select">                \x3Coption value="3">3 Items\x3C/option>                \x3Coption value="4">4 Items\x3C/option>                \x3Coption value="6">6 Items\x3C/option>                \x3Coption value="12" selected>12 Items\x3C/option>                \x3Coption value="24">24 Items\x3C/option>                \x3Coption value="48">48 Items\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Deal Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Only show products with active offers or previous prices (was_price)\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-deal-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Editor Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Enable multi-select to copy deals to CMS\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-editor-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">View Mode\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-view-mode-select">                \x3Coption value="auto">Auto Collection\x3C/option>                \x3Coption value="carousel">Carousel\x3C/option>                \x3Coption value="savings_squad">Savings Squad\x3C/option>                \x3Coption value="grid">Grid (Columns)\x3C/option>                \x3Coption value="row">Row (List)\x3C/option>              \x3C/select>            \x3C/div>          \x3C/div>        \x3C/div>      \x3C/div>      \x3Cdiv class="tg-df-filters">        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M9 3L5 6.99h3V14h2V6.99h3L9 3zm7 14.01V10h-2v7.01h-3L15 21l4-3.99h-3z"/>          \x3C/svg>          \x3Cselect class="tg-df-sort-select" aria-label="Sort Deals">            \x3Coption value="date_desc">Newest First\x3C/option>            \x3Coption value="best_match">Sort by: Match\x3C/option>            \x3Coption value="price_asc">Price Low to High\x3C/option>            \x3Coption value="price_desc">Price High to Low\x3C/option>            \x3Coption value="discount_desc">Biggest Discount\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>        \x3C/div>      \x3C/div>    \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();            if (['carousel', 'carousel-compact', 'auto', 'grid', 'row'].includes(this.getViewMode())) { this.loadCarouselSpreadsheet(); }        }        getViewMode() {          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          if (mode === 'carousel' || mode === 'auto' || mode === 'grid' || mode === 'row') {             if (mode === 'carousel') this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container') && mode === 'carousel') {               this.root.classList.add('is-carousel');             } else if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Everything';             if (this.discountFilter && !params.has('min_discount_ratio')) {               this.discountFilter.value = '5';             }          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (params.has('bg_color')) {            const bg = params.get('bg_color');            if (bg === 'white') {              this.root.style.setProperty('background-color', '#ffffff', 'important');            } else if (bg === 'transparent') {              this.root.style.setProperty('background-color', 'transparent', 'important');            } else if (bg === 'light_blue') {              this.root.style.setProperty('background-color', '#E7F0FF', 'important');            }          } else {             this.root.style.removeProperty('background-color');          }                    if (params.has('view_mode')) {            if (this.viewModeSelect) {              this.viewModeSelect.value = params.get('view_mode');            } else {              this.viewModeOverride = params.get('view_mode');            }          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'discount_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            this.searchInput.value = this.currentQuery;          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'discount_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const roundels = this.root.querySelectorAll('.tg-df-carousel-cat.original-hardcoded');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              if (this.getViewMode() === 'savings_squad' && this.autocompleteDropdown && this.airedaleTags && query.length > 0) {                 const matches = this.airedaleTags.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase()).slice(0, 5);                 if (matches.length > 0) {                    this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                    this.autocompleteDropdown.classList.add('active');                 } else {                    this.autocompleteDropdown.classList.remove('active');                 }              } else if (this.autocompleteDropdown) {                 this.autocompleteDropdown.classList.remove('active');              }              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  this.deals = [];                  this.render();                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                this.activeDealTag = null;                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });              this.activeDealTag = null;              this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.fetchDeals(query);              }            });          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = this.viewModeSelect.value === 'savings_squad' ? 'date_desc' : 'discount_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }                async loadCarouselSpreadsheet() {          try {              const parseCSVRow = (str) => {                  let result = [], cur = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (inQuotes) {                          if (char === '"') {                              if (str[i + 1] === '"') { cur += '"'; i++; }                              else { inQuotes = false; }                          } else { cur += char; }                      } else {                          if (char === '"') { inQuotes = true; }                          else if (char === ',') { result.push(cur); cur = ''; }                          else { cur += char; }                      }                  }                  result.push(cur); return result;              };              const parseCSV = (str) => {                  const rows = []; let curRow = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (char === '"') inQuotes = !inQuotes;                      if ((char === '\n' || char === '\r') && !inQuotes) {                          if (char === '\r' && str[i+1] === '\n') i++;                          if (curRow) rows.push(parseCSVRow(curRow));                          curRow = '';                      } else { curRow += char; }                  }                  if (curRow) rows.push(parseCSVRow(curRow));                  return rows;              };              const preloadedCSV = decodeURIComponent(escape(atob("LCwxLDIsMyw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNQ0KUm91bmRlbCB0ZXh0LEFsbCxUVnMsRm9vdHdlYXIsQXBwYXJlbCxNYXR0cmVzZXMsQXBwbGlhbmNlcyxXZWFyYWJsZSB0ZWNoLEhlYWRwaG9uZXMsU21hcnQgSG9tZSxTcGVha2VycyxMYXB0b3BzLFRhYmxldHMsQ29tcHV0aW5nLFBob25lcyxHYW1pbmcsTGVnbw0KUm91bmRlbCBpbWFnZSxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL2FpLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3R2cy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvN2IzYTIyNGIwNzk2M2M2MjdiNmI5MDliZDc4MzM4MzZlMDJmZjgxOS5qcGcud2VicCxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy84NGRhYzVkNDhlZDJkNDQ4NTU5ZWJhNjdhY2U4MzE0Y2M2N2NjZDk0LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vcHJvZHVjdHMvY2Fyb3VzZWwvbWF0dHJlc3Nlcy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvNzY4ZTk3Y2ViMDcxODAxZmFlMjA5MTBkMDgyMGIxNmY3NDdhZjkzOS5qcGcud2VicCxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3dlbGxuZXNzLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL2hlYWRwaG9uZXMuanBnLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzg5NTM1YmVlYmUyMGRiYmQ0YTM0NmQ2ZDZiZGZlOTFkOGE4ODRhMjEuanBnLndlYnAsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9hdWRpby5qcGcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9sYXB0b3BzLmpwZyxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy8yMzk3NTY0ZWQ3YTVmZjk0N2U5YjZiMzBlNTRmNDc0OTRiODQxZjg5LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vcHJvZHVjdHMvY2Fyb3VzZWwvY29tcHV0aW5nLmpwZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3Bob25lcy5wbmcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9nYW1pbmcucG5nLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzRmNmM2MjFjYWMwYmMxYTg1ZDU5M2UzNTk0YmE1YjM0OWVmZmQyOTIuanBnLndlYnANClNlYXJjaCBRdWVyeSxFdmVyeXRoaW5nLFRlbGV2aXNpb25zLCJTbmVha2VycywgcnVubmluZyBzaG9lcywgc2FuZGFscyIsQ2xvdGhpbmcsTWF0dHJlc3NlcyxIb21lIEFwcGxpYW5jZXMsV2VhcmFibGVzICYgRml0bmVzcyBUZWNoLEhlYWRwaG9uZXMsSG9tZSBUZWNoLFNwZWFrZXJzLExhcHRvcHMsVGFibGV0cyxDb21wdXRpbmcsUGhvbmVzLEdhbWluZyxDb25zdHJ1Y3Rpb24gVG95cw0KRGlzY291bnQgQW1vdW50LG1pbiA1JSxtaW4gMTAlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUNClByaWNlIFJhbmdlLCwsLCxtaW4gJDQwMCwsLCxtaW4gJDI1LCxtaW4gJDMwMCwsLG1pbiAkMTAwLCwNCkJyYW5kIFNlbGVjdGlvbiwsLCwsLCwsLCwsLCwsLCwNCkZpbHRlciBidXR0b25zLCwsLCwsLCwsLCwsLCwsLA0KMSxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMNCjIsQW1hem9uIGRlYWxzLFVuZGVyICQxMDAwLDUwJSBvZmYsQWRpZGFzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsNTAlIG9mZixBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscw0KMyxPdmVyICQ0MDAsVW5kZXIgJDUwMCxIb2thLE5pa2UsU2FhdHZhLE5pbmphLDQwJSBvZmYsSkxhYiwsSkJMLERlbGwsLEFzdXMsQXBwbGUsQ29uc29sZXMsU3RhciBXYXJzDQo0LFVuZGVyICQxMDAwLDUwJSBvZmYsU2tlY2hlcnMsVW5kZXIgQXJtb3VyLEhlbGl4LFNoYXJrLEdhcm1pbixBbmtlciBTb3VuZGNvcmUsUmluZyxTb25vcyxBcHBsZSxBcHBsZSxUUC1saW5rLFNhbXN1bmcsQWNjZXNzb3JpZXMsVW5kZXIgJDI1DQo1LFVuZGVyICQ1MDAsTEcsQXNpY3MsQ29sdW1iaWEsRHJlYW1DbG91ZCxLZXVyaWcsQXBwbGUsU29ueSxHb3ZlZSxUcmliaXQsTGVub3ZvLFNhbXN1bmcsRWVybyxHb29nbGUsR2FtZXMsVW5kZXIgJDUwDQo2LDUwJSBvZmYsU2Ftc3VuZyxOaWtlLFBhdGFnb25pYSxOZWN0YXIsRGUnTG9uZ2hpLEFtYXpmaXQsQXBwbGUsS2FzYSBzbWFydCxTb255LEFsaWVud2FyZSxUQ0wsTmV0Z2VhcixNb3Rvcm9sYSxOaW50ZW5kbyxCb3RhbmljYWxzDQo3LEFtYXpvbixIaXNlbnNlLE5ldyBCYWxhbmNlLEFyYyd0ZXJ5eCxUZW1wdXItcGVkaWMsRHlzb24sRml0Yml0LEJlYXRzLFBoaWxpcHMgSHVlLEFua2VyLEFjZXIsT25lUGx1cyxEZWxsLE9uZVBsdXMsU29ueSxEaXNuZXkNCjgsQXBwbGUsVENMLEFkaWRhcyxDYXJoYXJ0dCxCZWFyLEJpc3NlbGwsU2Ftc3VuZyxFYXJmdW4sQmxpbmssQmVhdHMsTVNJLE1pY3Jvc29mdCxBY2VyLE5vdGhpbmcsWGJveCxNYXJ2ZWwNCjksLFNvbnksU2F1Y29ueSxUaGUgTm9ydGggRmFjZSxTaWVuYSxOdXRyaWJ1bGxldCxPdXJhLFNhbXN1bmcsR29vZ2xlIE5lc3QgLE1hcnNoYWxsLFNhbXN1bmcsTGVub3ZvLExlbm92bywsLFBva2Vtb24NCjEwLCxSb2t1LEJpcmtlbnN0b2NrLENSWiBZb2dhLFdpbmtCZWRzLEJsYWNrIGFuZCBEZWNrZXIsUmluZ2Nvbm4sQ01GLEV1ZnksU2Ftc3VuZyxNaWNyb3NvZnQsUmVNYXJrYWJsZSxBbGllbndhcmUsLCwNCjExLCwsQnJvb2tzLFRoZSBHeW0gUGVvcGxlLEJyb29rbHluIGJlZGRpbmcsTmVzcHJlc3NvLCwxTW9yZSxBcmxvLCxSYXplciwsQ29yc2FpciwsLA0KMTIsLCxDcm9jcywsRWlnaHQgU2xlZXAsQ3Vpc2luYXJ0LCxKQkwsLCwsLEhQLCwsDQpOb3RlcywsLCwsLCwsLCwsLCwsLCwNCiwsIlByaW9yaXRpc2UgYmlnZ2VzdCAlLyQgZGlzY291bnQsIFR2cyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiB0aGUgbW9zdCBwb3B1bGFyIGV2ZW4gaWYgdGhleSBhcmUgc3RpbGwgZXhwZW5zaXZlIiwiTm8gcGF0dGVybiB0byBwcmljaW5nL2Rpc2NvdW50LCByZWFkZXJzIG1haW5seSBzaG9wIGJ5IGJyYW5kL3JlY29nbmlzYWJsZSBzaG9lcyIsIk5vIHBhdHRlcm4gdG8gcHJpY2luZy9kaXNjb3VudCwgcmVhZGVycyBtYWlubHkgc2hvcCBieSBicmFuZCIsIkEgbGFiZWwgd2lsbCBkZWZpbml0ZWx5IGhlbHAgaGVyZSBlLmcuIGJlc3QgZm9yIHNpZGUgc2xlZXBlciwgYmVzdCBtZW1vcnkgZm9hbSIsIkFwcGxpYW5jZXMgaXMgYSBiaWcgY2F0ZWdvcnksIGlzIGl0IHBvc3NpYmxlIHRvIHNwbGl0IGludG8ga2l0Y2hlbiBhcHBsaWFuY2VzLCBmbG9vcmNhcmUsIGFpciBoZWFsdGgvY29vbGluZz8gT3Igc2ltaWxhciIsIkZvY3VzIG9uIHZhbHVlIGZvciBtb25leSwgR2FybWlucyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiBwb3B1bGFyIGV2ZW4gdGhvdWdoIHRoZXkgYXJlIHN0aWxsICQ1MDAiLCwsLCxJbmNsdWRlIEtpbmRsZXMsSSB3b3VsZCBpbmNsdWRlIHdpZmkgcm91dGVycyBoZXJlIGluc3RlYWQgb2Ygc21hcnQgaG9tZSxDYW4gd2Ugc3VyZmFjZSBwaG9uZSBwcm92aWRlciBkZWFscz8gVC1tb2JpbGUgYW5kIHZlcml6b24gd291bGQgbWFrZSBhIGxvdCBtb3JlIG1vbmV5IHRoYW4gQW1hem9uLCwNCiwsaGF2aW5nIGEgJ2Jlc3QgZm9yJyBsYWJlbCB3b3VsZCBiZSBoZWxwZnVsIGUuZy4gYmVzdCBmb3IgYnJpZ2h0IHJvb20sQ2FuIHdlIHN0b3Aga2lkcyBzaG9lcyBmcm9tIHB1bGxpbmcgdGhyb3VnaD8sIldpbGwgdGhpcyBpbmNsdWRlIGFjY2Vzc29yaWVzIGUuZy4gY2FwcywgYmFncywgaWYgc28gbWFrZSBzdXJlIHRoZXNlIGFyZSBtaXhlZCB0aHJvdWdob3V0IGNsb3RoaW5nIGRlYWxzIixXaWxsIHRoaXMgaW5jbHVkZSB0b3BwZXJzIGFuZCBwaWxsb3dzPyBTZWVpbmcgbW9yZSBtb21lbnR1bSB3aXRoIHRoaXMgY2F0ZWdvcnkgcmVjZW50bHkgc28gYSBiZWRkaW5nIHRhYiBtaWdodCB3b3JrLCwiTmVlZCB0byBtYWtlIHN1cmUgYmFuZHMsIHNjcmVlbiBwcm90ZWN0b3JzIGV0Yy4gZG9uJ3QgcHVsbCBpbnRvIGhlcmUiLCwsLCwsLCwsDQosLCJQcmlvcml0aXNlIDY1JycgYW5kIDU1JyBpbmNoIFRWcywgdGhlbiBiaWdnZXIgc2NyZWVucyBiZWZvcmUgdGhlIHNtYWxsZXIgc2l6ZXMiLCwsUXVlZW4gaXMgdGhlIG1vc3QgcG9wdWxhciBzaXplIGluIHRoZSBVUyAtIHByaW9yaXRpc2UgZGVhbHMgZm9yIHRoaXMgc2l6ZSwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpDYXRlZ29yaWVzIHRvIGNvbnNpZGVyLCxQcm9kdWN0cyBpbmNsdWRlZCwsLCwsLCwsLCwsLCwsDQpVbmRlciAkNTA/LCxBaXIgdGFncywsLCwsLCwsLCwsLCwsDQosLFBvcnRhYmxlIGNoYXJnZXJzL3dpcmVsZXNzIGNoYXJnZXJzLCwsLCwsLCwsLCwsLCwNCiwsIldhdGVyIGJvdHRsZXMgKHN0YW5sZXlzLCBPd2FsYSwgSHlkcm8gZmxhc2ssIFlldGkpIiwsLCwsLCwsLCwsLCwsDQosLEhhbmQgaGVsZCBmYW5zLCwsLCwsLCwsLCwsLCwNCiwsLCwsLCwsLCwsLCwsLCwNCmhvbWUgb2ZmaWNlLCxvZmZpY2UgY2hhaXJzLCwsLCwsLCwsLCwsLCwNCiwsc3RhbmRpbmcgZGVza3MsLCwsLCwsLCwsLCwsLA0KLCxtb25pdG9ycywsLCwsLCwsLCwsLCwsDQosLEtleWJvYXJkcywsLCwsLCwsLCwsLCwsDQosLGRvY2tpbmcgc3RhdGlvbiwsLCwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpHYW1pbmcsLENvbnNvbGVzLCwsLCwsLCwsLCwsLCwNCiwsQWNjZXNzb3JpZXMsLCwsLCwsLCwsLCwsLA0KLCxHYW1lcywsLCwsLCwsLCwsLCwsDQosLENvdWxkIGluY2x1ZGUgTGVnbz8sLCwsLCwsLCwsLCwsLA==")));              const text = preloadedCSV;              const parsed = parseCSV(text);                            const rowsByName = {};              let filterStart = -1;              parsed.forEach((rc, i) => {                 if (rc && rc.length > 0 && rc[0]) rowsByName[rc[0]] = rc;                 if (rc && rc.length > 0 && rc[0] === 'Filter buttons') filterStart = i;              });                            const cols = [];              if(rowsByName['Roundel text']) {                const headerRow = rowsByName['Roundel text'];                for(let col = 1; col < headerRow.length; col++) {                   let label = headerRow[col];                   if (!label) continue;                                      let q = rowsByName['Search Query'] && rowsByName['Search Query'][col] ? rowsByName['Search Query'][col] : '';                   let img = rowsByName['Roundel image'] && rowsByName['Roundel image'][col] ? rowsByName['Roundel image'][col] : '';                   let ds = rowsByName['Discount Amount'] && rowsByName['Discount Amount'][col] ? rowsByName['Discount Amount'][col] : '';                   let pr = rowsByName['Price Range'] && rowsByName['Price Range'][col] ? rowsByName['Price Range'][col] : '';                   let rt = rowsByName['Retailer'] && rowsByName['Retailer'][col] ? rowsByName['Retailer'][col] : '';                   let ot = rowsByName['Offer Type'] && rowsByName['Offer Type'][col] ? rowsByName['Offer Type'][col] : '';                                      let filters = [];                   if(filterStart > 0) {                     for(let r = filterStart + 1; r < parsed.length; r++) {                         if(!parsed[r] || parsed[r][0] === 'Notes' || parsed[r][0] === 'Categories to consider') break;                         let f = parsed[r][col];                         if(f) filters.push(f);                     }                   }                   cols.push({ label, img, q, ds, pr, rt, ot, filters });                }              }              this.carouselData = cols;              if (this.carouselData && this.carouselData.length > 0) {                 const isMatched = this.carouselData.some(c => c.q === this.currentQuery || c.label === this.currentQuery);                 if (!isMatched) {                    const first = this.carouselData[0];                    this.currentQuery = first.q || first.label;                    if (this.priceFilter) this.priceFilter.value = 'all';                    if (this.customPriceMin) this.customPriceMin.value = '';                    if (this.customPriceMax) this.customPriceMax.value = '';                    let dPr = first.pr || 'all';                    if (typeof dPr === 'string' && dPr !== 'all') {                       let prLower = dPr.toLowerCase();                       if (prLower.includes('min') || prLower.includes('over')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else if (prLower.includes('max') || prLower.includes('under')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       }                    }                    let dAm = '0';                    if(first.ds && typeof first.ds === 'string') {                       let m = first.ds.match(/(\d+)/);                       if(m) dAm = m[1];                    }                    if (this.discountFilter) this.discountFilter.value = dAm;                    if (this.offerTypeSelect) this.offerTypeSelect.value = first.ot || '';                    if (this.retailerSelect) this.retailerSelect.value = first.rt || '';                    this.selectedBrands = [];                    if (this.brandDropdown) {                        const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                        chks.forEach(chk => chk.checked = false);                    }                    if (this.searchInput) this.searchInput.value = this.currentQuery;                 }              }              this.renderCarouselUI();          } catch(e){ console.warn(e); }        }                renderCarouselUI() {           const roundelWrapper = this.root.querySelector('.tg-df-carousel-roundels');           if(!roundelWrapper || !this.carouselData) return;                      let html = '';           this.carouselData.forEach(r => {              const q = r.q || r.label;              const isActive = (this.currentQuery === q || this.currentQuery === r.label) ? 'active' : '';              const imgHtml = r.img ? `\x3Cimg src="${r.img}" alt="${r.label}" />` : `\x3Csvg width="32" height="32" fill="#1F69FF" viewBox="0 0 24 24">\x3Cpath d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/>\x3C/svg>`;              html += `                \x3Cdiv class="tg-df-roundel tg-df-carousel-cat ${isActive}" data-label="${this.escapeHTML(r.label)}">                  \x3Cdiv class="tg-df-roundel-img-box">${imgHtml}\x3C/div>                  \x3Cspan class="tg-df-roundel-label">${this.escapeHTML(r.label)}\x3C/span>                \x3C/div>              `;           });           roundelWrapper.innerHTML = html;                      // Rebind clicks           const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');           roundels.forEach(rNode => {             rNode.addEventListener('click', () => {                const r = this.carouselData.find(c => c.label === rNode.getAttribute('data-label'));                 if(!r) return;                                  if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: r.label,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = r.q || r.label;                const labelTitle = this.root.querySelector('#tg-df-carousel-title-label');                if (labelTitle) labelTitle.textContent = 'Best ' + this.currentQuery;                if (this.priceFilter) this.priceFilter.value = 'all';                if (this.customPriceMin) this.customPriceMin.value = '';                if (this.customPriceMax) this.customPriceMax.value = '';                let dPr = r.pr || 'all';                if (typeof dPr === 'string' && dPr !== 'all') {                   let prLower = dPr.toLowerCase();                   if (prLower.includes('min') || prLower.includes('over')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMin) this.customPriceMin.value = m[1];                   } else if (prLower.includes('max') || prLower.includes('under')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMax) this.customPriceMax.value = m[1];                   }                }                                let discountAmount = '0';                if(r.ds && typeof r.ds === 'string') {                   let m = r.ds.match(/(\d+)/);                   if(m) discountAmount = m[1];                }                if (this.discountFilter) this.discountFilter.value = discountAmount;                if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                                // Clear brands                    this.selectedBrands = [];                    if (this.brandDropdown) {                    const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                    chks.forEach(chk => chk.checked = false);                }                                if (this.searchInput) this.searchInput.value = this.currentQuery;                                roundels.forEach(ro => ro.classList.remove('active'));                if (rNode) rNode.classList.add('active');                                this.renderCarouselFilters(r);                this.fetchDeals(this.currentQuery);             });           });                      // Auto-highlight active           const activeR = this.carouselData.find(c => c.q === this.currentQuery || c.label === this.currentQuery);           if(activeR) this.renderCarouselFilters(activeR);        }                renderCarouselFilters(r) {           const filtersWrap = this.root.querySelector('.tg-df-carousel-filters-wrap');           if(!filtersWrap) return;                      let html = `\x3Cbutton class="tg-df-carousel-filter-btn" data-type="all">All\x3C/button>`;                      r.filters.forEach(f => {              let fL = f.toLowerCase();              let icon = '';              let logic = `data-type="custom" data-v="${this.escapeHTML(f)}"`;              if (fL === 'amazon deals' || fL === 'prime deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>`;              } else if (fL === 'lightning deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>`;              } else {                 if (fL.includes('lightning')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-zap">\x3Cpolygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2">\x3C/polygon>\x3C/svg>`;                 } else if (fL.includes('% off')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>`;                 } else if (fL.includes('under') || fL.includes('min ')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>`;                 }                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>${icon} ${this.escapeHTML(f)}\x3C/button>`;              }           });                      filtersWrap.innerHTML = html;                      const btns = filtersWrap.querySelectorAll('button');           btns.forEach(b => {             b.addEventListener('click', () => {                const type = b.getAttribute('data-type');                if (type === 'custom') {                   const v = b.getAttribute('data-v');                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-custom-${(v||'').toLowerCase().replace(/[^a-z0-9]+/g, '-')}`, name: 'Custom Filter', label: v });                }                if (type === 'all') {                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: 'filter-clear-all', name: 'Clear all', label: 'Clear all filters' });                   // reset everything                   btns.forEach(btn => btn.classList.remove('active'));                   b.classList.add('active');                                      // Reset prices                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   if (this.brandDropdown) {                     const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                     chks.forEach(chk => chk.checked = false);                   }                } else {                   const v = b.getAttribute('data-v');                   const fL = v.toLowerCase();                                      let mapRet = ['amazon', 'walmart', 'best buy', 'target', 'john lewis', 'currys', 'argos'];                   const getCategory = (s) => {                      if (s === 'lightning deals' || s === 'amazon deals' || s === 'prime deals') return 'offer';                      if (s.includes('% off')) return 'discount';                      if (s.includes('under') || s.includes('over') || s.includes('min') || s.includes('max')) return 'price';                      if (mapRet.includes(s)) return 'retailer';                      return 'brand';                   };                   const cat = getCategory(fL);                   const wasActive = b.classList.contains('active');                   if (cat !== 'brand') {                      btns.forEach(btn => {                          if (btn === b) return;                          if (btn.getAttribute('data-type') === 'all') return;                          const bV = btn.getAttribute('data-v');                          if (!bV) return;                          if (getCategory(bV.toLowerCase()) === cat) btn.classList.remove('active');                      });                   }                   if (wasActive) b.classList.remove('active');                   else b.classList.add('active');                   let anyActive = Array.from(btns).some(btn => btn !== btns[0] && btn.classList.contains('active'));                   if (!anyActive) {                       btns[0].click();                       return;                   } else {                       btns[0].classList.remove('active');                   }                                      if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   btns.forEach(btn => {                       if (!btn.classList.contains('active') || btn.getAttribute('data-type') === 'all') return;                       const vv = btn.getAttribute('data-v');                       const vl = vv.toLowerCase();                                              if (vl === 'lightning deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_lightning';                       } else if (vl === 'amazon deals' || vl === 'prime deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_prime';                       } else if (vl.includes('% off')) {                          let m = vl.match(/(\d+)%/);                          if (m && this.discountFilter) this.discountFilter.value = m[1];                       } else if (vl.includes('under') || vl.includes('max')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       } else if (vl.includes('min') || vl.includes('over')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else {                          let foundR = mapRet.find(x => x === vl);                          if (foundR) {                             let realR = ['Amazon', 'Walmart', 'Best Buy', 'Target', 'John Lewis', 'Currys', 'Argos'].find(x => x.toLowerCase() === vl);                             if (this.retailerSelect) this.retailerSelect.value = realR;                          } else {                             this.selectedBrands.push(vv);                          }                       }                   });                                      if (this.brandDropdown) {                       const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                       chks.forEach(c => c.checked = this.selectedBrands.includes(c.value));                   }                                      if (r.pr && typeof r.pr === 'string') {                       let prL = r.pr.toLowerCase();                       if (prL.includes('under $')) {                           let m = prL.match(/under \$(\d+)/i);                           if (m && this.customPriceMax && !this.customPriceMax.value) this.customPriceMax.value = m[1];                       }                   }                }                                this.fetchDeals(this.currentQuery);             });           });                      // default to highlighting first           btns[0].classList.add('active');        }async fetchDeals(query, append = false) {          if (!append) {             this.showLoading();             this.deals = [];             this.displayLimit = this.getRowsLimit();          } else {             this.displayLimit += this.getRowsLimit();          }                    try {            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad(append);            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query, append);               } else {                 await this.fetchHawkDeals(query, append);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query, append);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const url = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let dynamicBrandsCounts = {};                    targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                   dynamicBrandsCounts[data.brand] = (dynamicBrandsCounts[data.brand] || 0) + 1;                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || ''                });             });          });                    const airedaleBrandsList = Object.keys(dynamicBrandsCounts).map(b => ({              formatted_value: b,              count: dynamicBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query, append = false) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (append && this.deals.length > 0) {            url.searchParams.append('offset', this.deals.length.toString());          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : (this.getViewMode() === 'savings_squad' ? 'date_desc' : 'discount_desc');          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin-top:8px;">${_div}                ${_div}              ${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)} (${this.airedaleTagCounts[tag] || 0})${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = isSavingsSquadMode ? 'View Deal' : 'Check Price';              if (isSavingsSquadMode) {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                  ${_div}                `;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = `                \x3Cdiv class="tg-df-card-merchant-wrapper">                  \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                ${_div}                \x3Cdiv class="tg-df-card-price-group">                  ${isSavingsSquadMode ? '' : `                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                  `}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description">\x3Cp>${this.escapeHTML(deal.description)}${_p}${_div}` : ''}                      ${_div}                    ${_div}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>${deal.isCheckPrice ? 'Check Price' : 'View Deal'}${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cp style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 12px; line-height: 1.4;">${this.escapeHTML(deal.description)}${_p}` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${priceGroupHtml}                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta ${isSavingsSquadMode ? 'tg-df-cta-savings-squad' : ''}" style="text-decoration: none;">${ctaText}${_a}                  ${_div}                ${_div}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit || ((this.getViewMode() === 'carousel' || this.getViewMode() === 'auto') && displayDeals.length > 0 && displayDeals.length % ((this.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12) === 0)) {            if (this.getViewMode() === 'carousel') {               dealsHtml += `                 \x3Cbutton type="button" class="tg-df-load-more-card tg-df-load-more">                   \x3Csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-bottom: 8px;">\x3Cpath d="M5 12h14">\x3C/path>\x3Cpath d="m12 5 7 7-7 7">\x3C/path>\x3C/svg>                   Load More                 ${_button}               `;            } else {               dealsHtml += `                 \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                   \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer; display: flex; align-items: center;">Load More${_button}                 ${_div}               `;            }          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }                    let gridWrapper = this.grid.parentElement;          if (gridWrapper && gridWrapper.classList.contains('tg-df-grid-wrapper')) {             let rightChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-right');             let leftChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-left');             if (this.getViewMode() === 'carousel') {                 // The observer set up in setupScrollListeners handles visibility.                 if (rightChevron) rightChevron.style.display = 'flex';                 if (leftChevron) leftChevron.style.display = 'none'; // reset correctly             } else {                 if (rightChevron) rightChevron.style.display = 'none';                 if (leftChevron) leftChevron.style.display = 'none';             }          }                    const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', async () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              if (displayDeals.length <= this.displayLimit) {                 loadMoreBtn.innerHTML = `                  <svg class="tg-df-spinner" style="width: 16px; height: 16px; display: inline-block; vertical-align: middle; margin-right: 8px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" d="M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48l2.83-2.83"/></svg>                  Loading...                 `;                 loadMoreBtn.disabled = true;                 await this.fetchDeals(this.currentQuery, true);              } else {                 this.displayLimit += this.getRowsLimit();                 this.render();              }            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            setTimeout(() => {               if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');               document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));            }, 50);          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Can rucking replace running for cardio? A strength coach and running expert weigh in ]]></title>
                                                                                                <dc:content><![CDATA[ <p>You've probably noticed there's a lot of debate about whether you need to run to improve cardio, or whether other activities like walking or hiking could replace it.</p><p>I'm a personal trainer who walks and runs for different reasons: I walk to ease stress, exercise (myself and my dog) and contribute toward my overall activity levels (known as <a href="https://www.tomsguide.com/features/non-exercise-activity-thermogenesis-why-neat-could-help-you-burn-more-calories">NEAT</a>), while I run to strengthen my heart and lungs and feel good.</p><p>But with the rise in rucking popularity, which involves walking with a weighted vest, I wanted to speak with those in the know to see if it could replace running for cardio. Below, a strength coach and running expert weigh in. </p><p>So, which is the cardio-building prize? Here's your final answer. </p><h3 class="article-body__section" id="section-benefits-of-rucking"><span>Benefits of rucking </span></h3><p>"<a href="https://www.tomsguide.com/wellness/fitness/forget-10-000-steps-i-tried-rucking-instead-of-regular-walking-for-one-week-and-its-a-game-changer">Rucking</a> offers several benefits, including improved cardiovascular fitness and muscular endurance, and increased functional capacity," says <a href="https://www.instagram.com/rebeccakennedynyc/" target="_blank" rel="nofollow">Rebecca Kennedy</a>, a strength coach and Peloton instructor. "It supports postural strength and endurance and provides a low-impact form of conditioning with adjustable intensity. Finally, it’s accessible and enjoyable."</p><p>"Rucking is certainly lower impact, with less ground-reaction forces, although foot injuries have been reported anecdotally," says running expert and coach <a href="https://www.instagram.com/performance_physique/" target="_blank" rel="nofollow">Arj</a><a href="https://www.instagram.com/performance_physique/" target="_blank">Thiruchelvam.</a> "There are certainly benefits to strength and posture and, in a calorie-controlled diet, this would help support fat loss.</p><p>"Running naturally poses a high injury rate amongst beginners and those with very high volumes or who are deconditioned," he adds. </p><h3 class="article-body__section" id="section-benefits-of-running"><span>Benefits of running </span></h3><p>"Running has been shown in a meta-analysis (Pedisic et al., 2020) to lead to substantial health and longevity benefits in addition to lower risk of all-cause mortality, starting with just one dose per week. It’s incredibly efficient at improving <a href="https://www.tomsguide.com/wellness/fitness/how-to-measure-your-vo2-max">VO2 Max</a> and also supporting bone health," Thiruchelvam tells us.</p><p>"Running is beneficial for your mental and metabolic health, muscular endurance, cardiovascular fitness, bone health, as well as joint and connective tissue capacity," adds Kennedy. "It’s also time-efficient and supports running-specific performance."</p><h3 class="article-body__section" id="section-can-rucking-replace-running-for-cardio"><span>Can rucking replace running for cardio?</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="HpYX5fj4EVBPLEFmZk253j" name="shutterstock_1432512671 (1) weighted walk" alt="Male running along a beach wearing a weighted vest" src="https://cdn.mos.cms.futurecdn.net/HpYX5fj4EVBPLEFmZk253j-1920-80.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: Shutterstock)</span></figcaption></figure><p>"It can, but<strong> it depends on your goal and what you're trying to achieve,</strong>" explains Kennedy. "First, I think it’s important to recognize that running is not a requirement for good cardiovascular health or overall fitness. Rather than asking a binary question (whether rucking can replace running), I'd encourage people to ask what they're hoping to accomplish through exercise. </p><p>"<strong>Both running and rucking can improve cardiovascular health, aerobic endurance, metabolic health and muscular conditioning</strong>, but they challenge the body differently. Running generally allows you to reach higher cardiovascular intensities and provides repetitive high impact, which can be super helpful in developing bone strength, joint and tendon capacity, and the ability to absorb and produce force. </p><p>"Rucking increases physical demands of walking by adding an external resistance. Rucking challenges our cardiovascular system, muscular endurance and postural muscles and ability to carry load without the repetitive high impact that running does."</p><p>On that note, Kennedy explains you don't get identical adaptations, and "<strong>one is not inherently better than the other</strong>." If you don't enjoy running, you can still do plyometrics, HIIT, jumping rope, or other sports like boxing or dancing to achieve the same types of fitness without running.</p><p>"We simply want to train our bodies to be capable, adaptable and resilient across a variety of physical demands. That being said, I think it's important to acknowledge both preferences, enjoyability, barrier to entry and current fitness level as guides," she adds.</p><div><blockquote><p>Both running and rucking can improve cardiovascular health, aerobic endurance, metabolic health and muscular conditioning, but they challenge the body differently. </p><p>Rebecca Kennedy, strength coach</p></blockquote></div><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="x6mfiVj98Bk9RZNUnhVqJV" name="running cap.jpg" alt="woman running with a cap on" src="https://cdn.mos.cms.futurecdn.net/x6mfiVj98Bk9RZNUnhVqJV-1920-80.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/jacoblund)</span></figcaption></figure><p>"Rucking can help people develop or maintain an aerobic base; that’s the lower-intensity, zone 1- zone 2 exercise," adds Thiruchelvam. "However, it certainly doesn’t help develop the higher intensity zones and associated muscular benefits that exist as a result of that faster-paced effort.</p><p>"The speed at which you perform the activity has a greater impact on physiological changes, and therefore, although rucking can elevate your heart rate, it cannot replicate the effect of running. In particular, heart rate can continue rising while oxygen levels off."</p><h3 class="article-body__section" id="section-contraindications"><span>Contraindications</span></h3><p>Thiruchelvam tells us that "<strong>running naturally poses a high injury rate amongst beginners</strong> and those with very high volumes or who are deconditioned... It’s also plausible to consider that the weight of the backpack may alter walking gait and mechanics."</p><p>He adds, "The <strong>contraindications to rucking revolve around current health and injuries of the spine, lower limbs, heart health and blood pressure</strong>, as usual. In addition to that, osteoporosis, surgeries, hernias and impaired balance are all serious considerations that need advice from a doctor."</p><p>"Rucking places additional load on your spine and can cause postural fatigue if the load is carried too long or is too heavy too soon," adds Kennedy. "It also may not be suitable for those seeking higher-impact or higher-intensity workouts. Finally, it’s not a replacement for strength training.</p><p>"<strong>My preference is to use a weighted vest over a backpack</strong> because the weight is distributed more evenly and it sits closer to your body, reducing any potential neck strain. If you don't have a vest and want to start, a backpack can work. Just make sure it’s snug, and the straps are pulled down so it isn't sagging in the back and the weight is distributed more evenly."</p><p>Kennedy adds, "<strong>While running has many benefits, it’s not the best for those who don’t enjoy it.</strong> Other things to consider are the repetitive impact and overuse; the higher recovery demands and barrier to entry; adaptation to running can take time; and finally individual limitations...if you have injuries, osteopenia, osteoporosis, or sarcopenia."</p><div><blockquote><p>Rucking places additional load on your spine and can cause postural fatigue if the load is carried too long or is too heavy too soon. It also may not be suitable for those seeking higher-impact or higher-intensity workouts.</p><p>Rebecca Kennedy.</p></blockquote></div><h3 class="article-body__section" id="section-how-to-choose-between-them"><span>How to choose between them</span></h3><p>"You may wish to incorporate rucking into your routine on easy days for more aerobic development or if you’re overweight or deconditioned and find running not yet realistic," recommends Thiruchelvam. "Running should be the priority if you want to run fast, for VO2 Max improvement, or if you have an upcoming race."</p><div><blockquote><p>You may wish to incorporate rucking into your routine on easy days for more aerobic development or if you’re overweight or deconditioned and find running not yet realistic.</p><p>Arj Thiruchelvam, running coach</p></blockquote></div><p>Kennedy suggests considering rucking if you don't enjoy running, want to reduce impact, and want to build postural strength and muscular endurance. You might also include rucking if you want to improve cardiovascular health and increase your load-carrying capabilities. Plus, it's an accessible way to increase the demands of your regular walks.</p><p>"Ultimately, both are valuable tools," she explains. "Personally, I enjoy the way I feel before, during and after a weighted vest walk. I love walking and think the weighted vest is a wonderful addition to my walks. </p><p>"You can be exceptionally fit without running. But being fit in one capacity doesn't automatically mean you're prepared for every physical demand. The goal should be to have a routine that trains you to be strong, capable, adaptable and resilient. Rucking and/or running should not be the only type of workout we do."</p><h3 class="article-body__section" id="section-verdict"><span>Verdict</span></h3><p>So, there you have it. You could replace your runs with rucks, and there are plenty of benefits, plus some drawbacks, for both. However, the demands aren't the same, and the outcomes aren't identical, which means you might need to add more variety into your routine to achieve various fitness goals. </p><p>Just remember that your body and any health conditions or injuries matter, so consider the benefits and downsides of both before deciding which benefit you most.</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><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="vGnNDN" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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/face-off/high-reps-vs-heavy-weights-which-is-better-for-building-muscle">High reps vs heavy weights</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/forget-running-or-jeffing-neuroscientist-andrew-huberman-says-this-is-the-secret-to-longevity-and-hitting-150-minutes-of-cardio-per-week">Forget running or 'Jeffing' — neuroscientist says this is the secret to longevity and hitting 150 minutes of cardio per week</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/forget-running-and-swimming-study-finds-this-sport-adds-10-years-to-your-life">Forget running and swimming — study finds this sport adds 10 years to your life</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness/can-rucking-replace-running-for-cardio-a-strength-coach-and-running-expert-weigh-in</link>
                                                                            <description>
                            <![CDATA[ I asked a strength coach and running expert whether rucking can replace cardio — here’s the truth. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">NmEzcUDpPC99HaEVdASKwm</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/GkxyW8YTSvfDTWFXfWsuwW-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 28 Oct 2026 09:00:00 +0000</pubDate>                                                                                                                                                                                                                                <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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/GkxyW8YTSvfDTWFXfWsuwW-1920-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock and Getty]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Woman rucking on left, woman running outdoors on right]]></media:description>                                                            <media:text><![CDATA[Woman rucking on left, woman running outdoors on right]]></media:text>
                                <media:title type="plain"><![CDATA[Woman rucking on left, woman running outdoors on right]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/GkxyW8YTSvfDTWFXfWsuwW-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>You've probably noticed there's a lot of debate about whether you need to run to improve cardio, or whether other activities like walking or hiking could replace it.</p><p>I'm a personal trainer who walks and runs for different reasons: I walk to ease stress, exercise (myself and my dog) and contribute toward my overall activity levels (known as <a href="https://www.tomsguide.com/features/non-exercise-activity-thermogenesis-why-neat-could-help-you-burn-more-calories">NEAT</a>), while I run to strengthen my heart and lungs and feel good.</p><p>But with the rise in rucking popularity, which involves walking with a weighted vest, I wanted to speak with those in the know to see if it could replace running for cardio. Below, a strength coach and running expert weigh in. </p><p>So, which is the cardio-building prize? Here's your final answer. </p><h3 class="article-body__section" id="section-benefits-of-rucking"><span>Benefits of rucking </span></h3><p>"<a href="https://www.tomsguide.com/wellness/fitness/forget-10-000-steps-i-tried-rucking-instead-of-regular-walking-for-one-week-and-its-a-game-changer">Rucking</a> offers several benefits, including improved cardiovascular fitness and muscular endurance, and increased functional capacity," says <a href="https://www.instagram.com/rebeccakennedynyc/" target="_blank" rel="nofollow">Rebecca Kennedy</a>, a strength coach and Peloton instructor. "It supports postural strength and endurance and provides a low-impact form of conditioning with adjustable intensity. Finally, it’s accessible and enjoyable."</p><p>"Rucking is certainly lower impact, with less ground-reaction forces, although foot injuries have been reported anecdotally," says running expert and coach <a href="https://www.instagram.com/performance_physique/" target="_blank" rel="nofollow">Arj</a><a href="https://www.instagram.com/performance_physique/" target="_blank">Thiruchelvam.</a> "There are certainly benefits to strength and posture and, in a calorie-controlled diet, this would help support fat loss.</p><p>"Running naturally poses a high injury rate amongst beginners and those with very high volumes or who are deconditioned," he adds. </p><h3 class="article-body__section" id="section-benefits-of-running"><span>Benefits of running </span></h3><p>"Running has been shown in a meta-analysis (Pedisic et al., 2020) to lead to substantial health and longevity benefits in addition to lower risk of all-cause mortality, starting with just one dose per week. It’s incredibly efficient at improving <a href="https://www.tomsguide.com/wellness/fitness/how-to-measure-your-vo2-max">VO2 Max</a> and also supporting bone health," Thiruchelvam tells us.</p><p>"Running is beneficial for your mental and metabolic health, muscular endurance, cardiovascular fitness, bone health, as well as joint and connective tissue capacity," adds Kennedy. "It’s also time-efficient and supports running-specific performance."</p><h3 class="article-body__section" id="section-can-rucking-replace-running-for-cardio"><span>Can rucking replace running for cardio?</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="HpYX5fj4EVBPLEFmZk253j" name="shutterstock_1432512671 (1) weighted walk" alt="Male running along a beach wearing a weighted vest" src="https://cdn.mos.cms.futurecdn.net/HpYX5fj4EVBPLEFmZk253j-1920-80.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: Shutterstock)</span></figcaption></figure><p>"It can, but<strong> it depends on your goal and what you're trying to achieve,</strong>" explains Kennedy. "First, I think it’s important to recognize that running is not a requirement for good cardiovascular health or overall fitness. Rather than asking a binary question (whether rucking can replace running), I'd encourage people to ask what they're hoping to accomplish through exercise. </p><p>"<strong>Both running and rucking can improve cardiovascular health, aerobic endurance, metabolic health and muscular conditioning</strong>, but they challenge the body differently. Running generally allows you to reach higher cardiovascular intensities and provides repetitive high impact, which can be super helpful in developing bone strength, joint and tendon capacity, and the ability to absorb and produce force. </p><p>"Rucking increases physical demands of walking by adding an external resistance. Rucking challenges our cardiovascular system, muscular endurance and postural muscles and ability to carry load without the repetitive high impact that running does."</p><p>On that note, Kennedy explains you don't get identical adaptations, and "<strong>one is not inherently better than the other</strong>." If you don't enjoy running, you can still do plyometrics, HIIT, jumping rope, or other sports like boxing or dancing to achieve the same types of fitness without running.</p><p>"We simply want to train our bodies to be capable, adaptable and resilient across a variety of physical demands. That being said, I think it's important to acknowledge both preferences, enjoyability, barrier to entry and current fitness level as guides," she adds.</p><div><blockquote><p>Both running and rucking can improve cardiovascular health, aerobic endurance, metabolic health and muscular conditioning, but they challenge the body differently. </p><p>Rebecca Kennedy, strength coach</p></blockquote></div><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="x6mfiVj98Bk9RZNUnhVqJV" name="running cap.jpg" alt="woman running with a cap on" src="https://cdn.mos.cms.futurecdn.net/x6mfiVj98Bk9RZNUnhVqJV-1920-80.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/jacoblund)</span></figcaption></figure><p>"Rucking can help people develop or maintain an aerobic base; that’s the lower-intensity, zone 1- zone 2 exercise," adds Thiruchelvam. "However, it certainly doesn’t help develop the higher intensity zones and associated muscular benefits that exist as a result of that faster-paced effort.</p><p>"The speed at which you perform the activity has a greater impact on physiological changes, and therefore, although rucking can elevate your heart rate, it cannot replicate the effect of running. In particular, heart rate can continue rising while oxygen levels off."</p><h3 class="article-body__section" id="section-contraindications"><span>Contraindications</span></h3><p>Thiruchelvam tells us that "<strong>running naturally poses a high injury rate amongst beginners</strong> and those with very high volumes or who are deconditioned... It’s also plausible to consider that the weight of the backpack may alter walking gait and mechanics."</p><p>He adds, "The <strong>contraindications to rucking revolve around current health and injuries of the spine, lower limbs, heart health and blood pressure</strong>, as usual. In addition to that, osteoporosis, surgeries, hernias and impaired balance are all serious considerations that need advice from a doctor."</p><p>"Rucking places additional load on your spine and can cause postural fatigue if the load is carried too long or is too heavy too soon," adds Kennedy. "It also may not be suitable for those seeking higher-impact or higher-intensity workouts. Finally, it’s not a replacement for strength training.</p><p>"<strong>My preference is to use a weighted vest over a backpack</strong> because the weight is distributed more evenly and it sits closer to your body, reducing any potential neck strain. If you don't have a vest and want to start, a backpack can work. Just make sure it’s snug, and the straps are pulled down so it isn't sagging in the back and the weight is distributed more evenly."</p><p>Kennedy adds, "<strong>While running has many benefits, it’s not the best for those who don’t enjoy it.</strong> Other things to consider are the repetitive impact and overuse; the higher recovery demands and barrier to entry; adaptation to running can take time; and finally individual limitations...if you have injuries, osteopenia, osteoporosis, or sarcopenia."</p><div><blockquote><p>Rucking places additional load on your spine and can cause postural fatigue if the load is carried too long or is too heavy too soon. It also may not be suitable for those seeking higher-impact or higher-intensity workouts.</p><p>Rebecca Kennedy.</p></blockquote></div><h3 class="article-body__section" id="section-how-to-choose-between-them"><span>How to choose between them</span></h3><p>"You may wish to incorporate rucking into your routine on easy days for more aerobic development or if you’re overweight or deconditioned and find running not yet realistic," recommends Thiruchelvam. "Running should be the priority if you want to run fast, for VO2 Max improvement, or if you have an upcoming race."</p><div><blockquote><p>You may wish to incorporate rucking into your routine on easy days for more aerobic development or if you’re overweight or deconditioned and find running not yet realistic.</p><p>Arj Thiruchelvam, running coach</p></blockquote></div><p>Kennedy suggests considering rucking if you don't enjoy running, want to reduce impact, and want to build postural strength and muscular endurance. You might also include rucking if you want to improve cardiovascular health and increase your load-carrying capabilities. Plus, it's an accessible way to increase the demands of your regular walks.</p><p>"Ultimately, both are valuable tools," she explains. "Personally, I enjoy the way I feel before, during and after a weighted vest walk. I love walking and think the weighted vest is a wonderful addition to my walks. </p><p>"You can be exceptionally fit without running. But being fit in one capacity doesn't automatically mean you're prepared for every physical demand. The goal should be to have a routine that trains you to be strong, capable, adaptable and resilient. Rucking and/or running should not be the only type of workout we do."</p><h3 class="article-body__section" id="section-verdict"><span>Verdict</span></h3><p>So, there you have it. You could replace your runs with rucks, and there are plenty of benefits, plus some drawbacks, for both. However, the demands aren't the same, and the outcomes aren't identical, which means you might need to add more variety into your routine to achieve various fitness goals. </p><p>Just remember that your body and any health conditions or injuries matter, so consider the benefits and downsides of both before deciding which benefit you most.</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><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="vGnNDN" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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/face-off/high-reps-vs-heavy-weights-which-is-better-for-building-muscle">High reps vs heavy weights</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/forget-running-or-jeffing-neuroscientist-andrew-huberman-says-this-is-the-secret-to-longevity-and-hitting-150-minutes-of-cardio-per-week">Forget running or 'Jeffing' — neuroscientist says this is the secret to longevity and hitting 150 minutes of cardio per week</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/forget-running-and-swimming-study-finds-this-sport-adds-10-years-to-your-life">Forget running and swimming — study finds this sport adds 10 years to your life</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ The North Face is up to 50% off at Amazon, REI and more — shop these 11 deals for fall ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Ready to refresh your wardrobe for the cooler months ahead? The North Face has you covered with versatile styles designed for everything from crisp fall days to the coldest winter weather. While the brand tends to be a bit pricey, several retailers are currently offering discounts on some of its most popular styles. </p><p>In fact, Amazon, REI and the official North Face site are <a href="https://www.thenorthface.com/en-us/c/sale-829803" target="_blank" rel="nofollow">knocking up to 50% off select styles</a>. Whether you're planning to hit the trails, explore the great outdoors or brave a rainstorm, The North Face has the perfect pieces to keep you comfortable as temperatures start to drop. </p><p>To take advantage of these incredible deals, keep on reading for all my favorite picks from The North Face sale. </p><h2 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h2><ul><li><strong></strong><a href="https://www.thenorthface.com/en-us/c/sale-829803" target="_blank" rel="nofollow"><strong>shop all The North Face deals</strong></a></li><li><strong></strong><a href="https://www.rei.com/b/the-north-face/f/scd-deals?" target="_blank" rel="nofollow"><strong>shop all The North Face deals at REI</strong></a></li><li><a href="https://www.amazon.com/stores/THENORTHFACE/page/4CB8EA89-2A36-48BC-A2C2-E23C816F9339" target="_blank" rel="nofollow"><strong>shop all The North Face deals at Amazon</strong></a></li><li><strong>The North Face Sunriser Hoodie (Men's): </strong><a href="https://www.thenorthface.com/en-us/p/mens/mens-tops/mens-active-tops-224210/mens-lightrange-sunriser-hoodie-NF0A8BN8?color=BQ1" target="_blank" rel="nofollow"><strong>was $80 now $56</strong></a></li><li><strong>The North Face Jester Everyday Laptop Backpack: </strong><a href="https://www.amazon.com/North-Face-Womens-Everyday-Backpack/dp/B0CNB261KH?" target="_blank" rel="nofollow"><strong>was $75 now $59</strong></a></li><li><strong>The North Face Osito Lux Jacket (Women's): </strong><a href="https://www.rei.com/product/250475/the-north-face-osito-lux-jacket-womens" target="_blank" rel="nofollow"><strong>was $130 now $65</strong></a></li><li><strong>The North Face Antora Jacket (Women's): </strong><a href="https://www.amazon.com/dp/B0F97WG8SQ?" target="_blank" rel="nofollow"><strong>was $130 now $91</strong></a></li><li><strong>The North Face Aconcagua 3 Jacket (Men's): </strong><a href="https://www.amazon.com/dp/B0F1WYVHWW?" target="_blank" rel="nofollow"><strong>was $200 now $135</strong></a></li></ul><h2 class="article-body__section" id="section-the-north-face-apparel-deals"><span>The North Face Apparel Deals</span></h2><div class="product"><a data-dimension112="fcbd0e92-d216-11f1-b272-33d8352bb2bb" data-action="Deal Block" data-label="Dock Worker Recycled Beanie" data-dimension48="Dock Worker Recycled Beanie" data-dimension25="$27" href="https://www.amazon.com/NORTH-FACE-Worker-Recycled-Beanie/dp/B0BGY9SS51" 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:95.29%;"><img id="LtEEx8hgM2qRA4YM6Ydh4C" name="Dock Worker Recycled Beanie" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/LtEEx8hgM2qRA4YM6Ydh4C-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="647" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>Right now this Dock Worker Recycled Beanie from The North Face is on sale starting from $27. It's super stylish thanks to its range of muted color options and The North Face logo patch. Plus, its deep fit maximizes warmth.<a class="view-deal button" href="https://www.amazon.com/NORTH-FACE-Worker-Recycled-Beanie/dp/B0BGY9SS51" target="_blank" rel="nofollow" data-dimension112="fcbd0e92-d216-11f1-b272-33d8352bb2bb" data-action="Deal Block" data-label="Dock Worker Recycled Beanie" data-dimension48="Dock Worker Recycled Beanie" data-dimension25="$27">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd0f00-d216-11f1-a965-bd9bde873bdf" data-action="Deal Block" data-label="Jester Daypack" data-dimension48="Jester Daypack" data-dimension25="$44" href="https://www.rei.com/product/165715/the-north-face-jester-daypack" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="jFFtPWzRmj9f42irAm3fsS" name="north face deals" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jFFtPWzRmj9f42irAm3fsS-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/165715/the-north-face-jester-daypack" target="_blank" rel="nofollow" data-dimension112="fcbd0f00-d216-11f1-a965-bd9bde873bdf" data-action="Deal Block" data-label="Jester Daypack" data-dimension48="Jester Daypack" data-dimension25="$44">Jester Daypack: was $75 now $44</a></strong><br />This backpack features tons of compartments — including a laptop sleeve — and can even stand up on its own. Its padded shoulder straps offer comfort and it also has two grab handles on top making it convenient to open and provide a balanced carry. It’s also endorsed by the American Chiropractic Association thanks to its comfortable FlexVent suspension system.<a class="view-deal button" href="https://www.rei.com/product/165715/the-north-face-jester-daypack" target="_blank" rel="nofollow" data-dimension112="fcbd0f00-d216-11f1-a965-bd9bde873bdf" data-action="Deal Block" data-label="Jester Daypack" data-dimension48="Jester Daypack" data-dimension25="$44">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd0f6e-d216-11f1-b195-b36487b322c8" data-action="Deal Block" data-label="Sunriser Hoodie (Men's)" data-dimension48="Sunriser Hoodie (Men's)" data-dimension25="$56" href="https://www.thenorthface.com/en-us/p/mens/mens-tops/mens-active-tops-224210/mens-sunriser-hoodie-NF0A8BN8?color=2EL" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:688px;"><p class="vanilla-image-block" style="padding-top:116.28%;"><img id="3JpsW9Lw9CUbH56rbBPUh4" name="sunriser hoodie" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3JpsW9Lw9CUbH56rbBPUh4-1920-80.jpg" mos="" align="middle" fullscreen="" width="688" height="800" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.thenorthface.com/en-us/p/mens/mens-tops/mens-active-tops-224210/mens-sunriser-hoodie-NF0A8BN8?color=2EL" target="_blank" rel="nofollow" data-dimension112="fcbd0f6e-d216-11f1-b195-b36487b322c8" data-action="Deal Block" data-label="Sunriser Hoodie (Men's)" data-dimension48="Sunriser Hoodie (Men's)" data-dimension25="$56">Sunriser Hoodie (Men's): was $80 now $56</a></strong><br />This attractive hoodie has more going for it than just looks, thanks to The North Face’s Lightrange finish, which provides UPF protection, anti-odor technology, and moisture-wicking properties. It also has reflective elements on the chest and back, making it a great pick for evening runners.<a class="view-deal button" href="https://www.thenorthface.com/en-us/p/mens/mens-tops/mens-active-tops-224210/mens-sunriser-hoodie-NF0A8BN8?color=2EL" target="_blank" rel="nofollow" data-dimension112="fcbd0f6e-d216-11f1-b195-b36487b322c8" data-action="Deal Block" data-label="Sunriser Hoodie (Men's)" data-dimension48="Sunriser Hoodie (Men's)" data-dimension25="$56">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd0fdc-d216-11f1-ab39-3f5c93417ad0" data-action="Deal Block" data-label="Jester Everyday Laptop Backpack" data-dimension48="Jester Everyday Laptop Backpack" data-dimension25="$59" href="https://www.amazon.com/North-Face-Womens-Everyday-Backpack/dp/B0CNB261KH?" 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:116.35%;"><img id="JiduFGLLchFPwftiHi7DLN" name="" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/JiduFGLLchFPwftiHi7DLN-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="790" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/North-Face-Womens-Everyday-Backpack/dp/B0CNB261KH?" target="_blank" rel="nofollow" data-dimension112="fcbd0fdc-d216-11f1-ab39-3f5c93417ad0" data-action="Deal Block" data-label="Jester Everyday Laptop Backpack" data-dimension48="Jester Everyday Laptop Backpack" data-dimension25="$59">Jester Everyday Laptop Backpack: was $90 now $59</a></strong><br />The North Face Jester backpack is the ideal campus backpack. It has a 30 liter capacity, a padded 15-inch laptop sleeve, and a front organization pocket with mesh water bottle holders. <a class="view-deal button" href="https://www.amazon.com/North-Face-Womens-Everyday-Backpack/dp/B0CNB261KH?" target="_blank" rel="nofollow" data-dimension112="fcbd0fdc-d216-11f1-ab39-3f5c93417ad0" data-action="Deal Block" data-label="Jester Everyday Laptop Backpack" data-dimension48="Jester Everyday Laptop Backpack" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd104a-d216-11f1-a908-2d7a86d54645" data-action="Deal Block" data-label="DotKnit Thermal ¼-Zip (Women's)" data-dimension48="DotKnit Thermal ¼-Zip (Women's)" data-dimension25="$64" href="https://www.rei.com/product/254013/the-north-face-dotknit-thermal-quarter-zip-pullover-womens?color=MIDNIGHT%2520PETROL" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:576px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="JkvuGYs7dyyBgbeoS9VyUF" name="The North Face dotknot" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/JkvuGYs7dyyBgbeoS9VyUF-1920-80.jpg" mos="" align="middle" fullscreen="" width="576" height="576" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/254013/the-north-face-dotknit-thermal-quarter-zip-pullover-womens?color=MIDNIGHT%2520PETROL" target="_blank" rel="nofollow" data-dimension112="fcbd104a-d216-11f1-a908-2d7a86d54645" data-action="Deal Block" data-label="DotKnit Thermal ¼-Zip (Women's)" data-dimension48="DotKnit Thermal ¼-Zip (Women's)" data-dimension25="$64">DotKnit Thermal ¼-Zip (Women's): was $90 now $64</a></strong><br />If you're a runner, you need this ¼-zip for the colder months. Not only does it help regulate body temperature with its innovative insulating fabric, it also actively moves moisture away from the body.<a class="view-deal button" href="https://www.rei.com/product/254013/the-north-face-dotknit-thermal-quarter-zip-pullover-womens?color=MIDNIGHT%2520PETROL" target="_blank" rel="nofollow" data-dimension112="fcbd104a-d216-11f1-a908-2d7a86d54645" data-action="Deal Block" data-label="DotKnit Thermal ¼-Zip (Women's)" data-dimension48="DotKnit Thermal ¼-Zip (Women's)" data-dimension25="$64">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd10b8-d216-11f1-b523-4bdef0e8ca60" data-action="Deal Block" data-label="Osito Lux Jacket (Women's)" data-dimension48="Osito Lux Jacket (Women's)" data-dimension25="$65" href="https://www.rei.com/product/250475/the-north-face-osito-lux-jacket-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1290px;"><p class="vanilla-image-block" style="padding-top:116.28%;"><img id="MZdvPZM2QPb9UsJtviZ5GJ" name="Osito Lux Jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/MZdvPZM2QPb9UsJtviZ5GJ-1920-80.jpg" mos="" align="middle" fullscreen="" width="1290" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/250475/the-north-face-osito-lux-jacket-womens" target="_blank" rel="nofollow" data-dimension112="fcbd10b8-d216-11f1-b523-4bdef0e8ca60" data-action="Deal Block" data-label="Osito Lux Jacket (Women's)" data-dimension48="Osito Lux Jacket (Women's)" data-dimension25="$65">Osito Lux Jacket (Women's): was $130 now $65</a></strong><br />The super soft Osito Jacket is made with a supersoft high-pile fleece and provides instant, lightweight warmth. It has a rib-knit collar, hem and cuffs for better warmth retention in chilly weather.<a class="view-deal button" href="https://www.rei.com/product/250475/the-north-face-osito-lux-jacket-womens" target="_blank" rel="nofollow" data-dimension112="fcbd10b8-d216-11f1-b523-4bdef0e8ca60" data-action="Deal Block" data-label="Osito Lux Jacket (Women's)" data-dimension48="Osito Lux Jacket (Women's)" data-dimension25="$65">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd1180-d216-11f1-8860-8be4a04140ad" data-action="Deal Block" data-label="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension48="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension25="$74" href="https://www.rei.com/product/C00697/the-north-face-yumiori-off-peak-full-zip-jacket-womens" 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="vamU4Ky2CB4QQda8nfrvm4" name="the north face yumiori jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vamU4Ky2CB4QQda8nfrvm4-1920-80.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C00697/the-north-face-yumiori-off-peak-full-zip-jacket-womens" target="_blank" rel="nofollow" data-dimension112="fcbd1180-d216-11f1-8860-8be4a04140ad" data-action="Deal Block" data-label="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension48="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension25="$74">Yumiori Off Peak Full-Zip Jacket - Women's: was $150 now $74</a></strong><br />The North Face's Yumiori fleece is a perfect hiking-slash-everyday fleece. Smartphones fit snugly into the chest pocket, one zipper even doubles as a hair tie, and it's finished with durable water repellent.<a class="view-deal button" href="https://www.rei.com/product/C00697/the-north-face-yumiori-off-peak-full-zip-jacket-womens" target="_blank" rel="nofollow" data-dimension112="fcbd1180-d216-11f1-8860-8be4a04140ad" data-action="Deal Block" data-label="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension48="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension25="$74">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd1248-d216-11f1-8850-a78ea49d6b96" data-action="Deal Block" data-label="Kikash Wind Jacket (Women's)" data-dimension48="Kikash Wind Jacket (Women's)" data-dimension25="$75" href="https://www.rei.com/product/254048/the-north-face-kikash-wind-jacket-womens" 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="euVM6xCmm2F8CfG6fPp57T" name="Kikash jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/euVM6xCmm2F8CfG6fPp57T-1920-80.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/254048/the-north-face-kikash-wind-jacket-womens" target="_blank" rel="nofollow" data-dimension112="fcbd1248-d216-11f1-8850-a78ea49d6b96" data-action="Deal Block" data-label="Kikash Wind Jacket (Women's)" data-dimension48="Kikash Wind Jacket (Women's)" data-dimension25="$75">Kikash Wind Jacket (Women's): was $150 now $75</a></strong><br />The Kikash Wind Jacket is built for those days when the wind won't quit. The durable nylon fabric shrugs off mountain gusts while keeping you mobile, and reflective details add crucial visibility for early starts or late finishes. The secure zip pockets and snug elastic hem make it a reliable companion for unpredictable conditions.<a class="view-deal button" href="https://www.rei.com/product/254048/the-north-face-kikash-wind-jacket-womens" target="_blank" rel="nofollow" data-dimension112="fcbd1248-d216-11f1-8850-a78ea49d6b96" data-action="Deal Block" data-label="Kikash Wind Jacket (Women's)" data-dimension48="Kikash Wind Jacket (Women's)" data-dimension25="$75">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd13d8-d216-11f1-a8bb-b763a0088eca" data-action="Deal Block" data-label="TNF Performance Fleece 1/4 Zip Jacket (Women's)" data-dimension48="TNF Performance Fleece 1/4 Zip Jacket (Women's)" data-dimension25="$80" href="https://www.amazon.com/dp/B0FX8Z9VH4?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:662px;"><p class="vanilla-image-block" style="padding-top:226.59%;"><img id="4xm4Hfhke6ZnYYKS66BiEd" name="TNF Performance Fleece 1/4 Zip Jacket (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4xm4Hfhke6ZnYYKS66BiEd-1920-80.jpg" mos="" align="middle" fullscreen="" width="662" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0FX8Z9VH4?" target="_blank" rel="nofollow" data-dimension112="fcbd13d8-d216-11f1-a8bb-b763a0088eca" data-action="Deal Block" data-label="TNF Performance Fleece 1/4 Zip Jacket (Women's)" data-dimension48="TNF Performance Fleece 1/4 Zip Jacket (Women's)" data-dimension25="$80">TNF Performance Fleece 1/4 Zip Jacket (Women's): was $90 now $80</a></strong><br />It's hard to say no to this cozy fleece. It's made of soft polyester fleece, with an athletic look and lightweight feel. Make sure to grab one to layer up when temperatures drop on crisp fall days.<a class="view-deal button" href="https://www.amazon.com/dp/B0FX8Z9VH4?" target="_blank" rel="nofollow" data-dimension112="fcbd13d8-d216-11f1-a8bb-b763a0088eca" data-action="Deal Block" data-label="TNF Performance Fleece 1/4 Zip Jacket (Women's)" data-dimension48="TNF Performance Fleece 1/4 Zip Jacket (Women's)" data-dimension25="$80">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd1446-d216-11f1-8253-5325d17d1fdd" data-action="Deal Block" data-label="Antora Jacket (Women's)" data-dimension48="Antora Jacket (Women's)" data-dimension25="$91" href="https://www.amazon.com/North-Face-Waterproof-Windproof-Adjustable/dp/B0F97WG8SQ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:731px;"><p class="vanilla-image-block" style="padding-top:205.20%;"><img id="bN5BuTC38YdrnSkcwmxwpg" name="Antora Jacket (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bN5BuTC38YdrnSkcwmxwpg-1920-80.jpg" mos="" align="middle" fullscreen="" width="731" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/North-Face-Waterproof-Windproof-Adjustable/dp/B0F97WG8SQ" target="_blank" rel="nofollow" data-dimension112="fcbd1446-d216-11f1-8253-5325d17d1fdd" data-action="Deal Block" data-label="Antora Jacket (Women's)" data-dimension48="Antora Jacket (Women's)" data-dimension25="$91">Antora Jacket (Women's): was $130 now $91</a></strong><br />$91 is a great deal for this lightweight, weather-resistant shell. A core piece of outerwear no one should leave home without, the Antora Jacket boasts impressive rain-repellent capabilities. A drawstring-adjustable hood provides extra H2O protection, while a storm flap protects the main zipper from seepage during downpours. More importantly, as far as rain shells go, few can match the style factor of the Antora. <a class="view-deal button" href="https://www.amazon.com/North-Face-Waterproof-Windproof-Adjustable/dp/B0F97WG8SQ" target="_blank" rel="nofollow" data-dimension112="fcbd1446-d216-11f1-8253-5325d17d1fdd" data-action="Deal Block" data-label="Antora Jacket (Women's)" data-dimension48="Antora Jacket (Women's)" data-dimension25="$91">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd14b4-d216-11f1-b60b-737447380189" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$135" href="https://www.amazon.com/dp/B0F1WYVHWW?" 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:187.78%;"><img id="jLN4YbW223nKsxQxPVPWZR" name="TNF jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jLN4YbW223nKsxQxPVPWZR-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1275" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0F1WYVHWW?" target="_blank" rel="nofollow" data-dimension112="fcbd14b4-d216-11f1-b60b-737447380189" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$135">Aconcagua 3 Jacket (Men's): was $200 now $135</a></strong><br />This lightweight puffer blends recycled down with synthetic insulation for maximum warmth and weather resistance in a tidy, easy-to-stow package. Zonal sheet insulation and a water-repellant finish round out the feature set.<a class="view-deal button" href="https://www.amazon.com/dp/B0F1WYVHWW?" target="_blank" rel="nofollow" data-dimension112="fcbd14b4-d216-11f1-b60b-737447380189" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$135">View Deal</a></p></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness/the-north-face-is-up-to-50-percent-off-at-amazon-rei-and-more-shop-these-11-deals-for-fall</link>
                                                                            <description>
                            <![CDATA[ North Face is hosting a huge sale with up to 50% off. Score deals on jackets, fleeces and backpacks. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">HJNDMudK9EKEAdsifxTGyn</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/uZdJ8sgZfkjBcSHtWd5MyS-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 27 Oct 2026 15:14:50 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Fitness]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Olivia Halevy ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/YAg7Fmh9dGKbg3hULBMWiU-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Olivia is a Deals Writer at Tom’s Guide. She loves all things lifestyle, shopping and sourcing the best deals from some of the top brands, retailers and websites around. From fashion and beauty to smart home and tech, she has an eye for finding practical, stylish, and reasonably-priced items that help make life simpler (and a little more aesthetically-pleasing).&amp;nbsp;Olivia has over five years of experience writing lifestyle, commerce, and branded content for &lt;a href=&quot;http://patch.com/&quot;&gt;Patch.com&lt;/a&gt;. She&#039;s covered major shopping holidays like Amazon Prime Day, Black Friday and Cyber Monday. In her free time, she enjoys trying out new exercise classes, binge-watching the latest viral TV shows, cooking, spending time with family and taking long walks with her dog, Gus.&amp;nbsp;&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/uZdJ8sgZfkjBcSHtWd5MyS-1920-80.jpg">
                                                            <media:credit><![CDATA[The North Face / edited by Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[The North Face]]></media:description>                                                            <media:text><![CDATA[The North Face]]></media:text>
                                <media:title type="plain"><![CDATA[The North Face]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/uZdJ8sgZfkjBcSHtWd5MyS-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Ready to refresh your wardrobe for the cooler months ahead? The North Face has you covered with versatile styles designed for everything from crisp fall days to the coldest winter weather. While the brand tends to be a bit pricey, several retailers are currently offering discounts on some of its most popular styles. </p><p>In fact, Amazon, REI and the official North Face site are <a href="https://www.thenorthface.com/en-us/c/sale-829803" target="_blank" rel="nofollow">knocking up to 50% off select styles</a>. Whether you're planning to hit the trails, explore the great outdoors or brave a rainstorm, The North Face has the perfect pieces to keep you comfortable as temperatures start to drop. </p><p>To take advantage of these incredible deals, keep on reading for all my favorite picks from The North Face sale. </p><h2 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h2><ul><li><strong></strong><a href="https://www.thenorthface.com/en-us/c/sale-829803" target="_blank" rel="nofollow"><strong>shop all The North Face deals</strong></a></li><li><strong></strong><a href="https://www.rei.com/b/the-north-face/f/scd-deals?" target="_blank" rel="nofollow"><strong>shop all The North Face deals at REI</strong></a></li><li><a href="https://www.amazon.com/stores/THENORTHFACE/page/4CB8EA89-2A36-48BC-A2C2-E23C816F9339" target="_blank" rel="nofollow"><strong>shop all The North Face deals at Amazon</strong></a></li><li><strong>The North Face Sunriser Hoodie (Men's): </strong><a href="https://www.thenorthface.com/en-us/p/mens/mens-tops/mens-active-tops-224210/mens-lightrange-sunriser-hoodie-NF0A8BN8?color=BQ1" target="_blank" rel="nofollow"><strong>was $80 now $56</strong></a></li><li><strong>The North Face Jester Everyday Laptop Backpack: </strong><a href="https://www.amazon.com/North-Face-Womens-Everyday-Backpack/dp/B0CNB261KH?" target="_blank" rel="nofollow"><strong>was $75 now $59</strong></a></li><li><strong>The North Face Osito Lux Jacket (Women's): </strong><a href="https://www.rei.com/product/250475/the-north-face-osito-lux-jacket-womens" target="_blank" rel="nofollow"><strong>was $130 now $65</strong></a></li><li><strong>The North Face Antora Jacket (Women's): </strong><a href="https://www.amazon.com/dp/B0F97WG8SQ?" target="_blank" rel="nofollow"><strong>was $130 now $91</strong></a></li><li><strong>The North Face Aconcagua 3 Jacket (Men's): </strong><a href="https://www.amazon.com/dp/B0F1WYVHWW?" target="_blank" rel="nofollow"><strong>was $200 now $135</strong></a></li></ul><h2 class="article-body__section" id="section-the-north-face-apparel-deals"><span>The North Face Apparel Deals</span></h2><div class="product"><a data-dimension112="fcbd0e92-d216-11f1-b272-33d8352bb2bb" data-action="Deal Block" data-label="Dock Worker Recycled Beanie" data-dimension48="Dock Worker Recycled Beanie" data-dimension25="$27" href="https://www.amazon.com/NORTH-FACE-Worker-Recycled-Beanie/dp/B0BGY9SS51" 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:95.29%;"><img id="LtEEx8hgM2qRA4YM6Ydh4C" name="Dock Worker Recycled Beanie" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/LtEEx8hgM2qRA4YM6Ydh4C-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="647" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>Right now this Dock Worker Recycled Beanie from The North Face is on sale starting from $27. It's super stylish thanks to its range of muted color options and The North Face logo patch. Plus, its deep fit maximizes warmth.<a class="view-deal button" href="https://www.amazon.com/NORTH-FACE-Worker-Recycled-Beanie/dp/B0BGY9SS51" target="_blank" rel="nofollow" data-dimension112="fcbd0e92-d216-11f1-b272-33d8352bb2bb" data-action="Deal Block" data-label="Dock Worker Recycled Beanie" data-dimension48="Dock Worker Recycled Beanie" data-dimension25="$27">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd0f00-d216-11f1-a965-bd9bde873bdf" data-action="Deal Block" data-label="Jester Daypack" data-dimension48="Jester Daypack" data-dimension25="$44" href="https://www.rei.com/product/165715/the-north-face-jester-daypack" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="jFFtPWzRmj9f42irAm3fsS" name="north face deals" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jFFtPWzRmj9f42irAm3fsS-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/165715/the-north-face-jester-daypack" target="_blank" rel="nofollow" data-dimension112="fcbd0f00-d216-11f1-a965-bd9bde873bdf" data-action="Deal Block" data-label="Jester Daypack" data-dimension48="Jester Daypack" data-dimension25="$44">Jester Daypack: was $75 now $44</a></strong><br />This backpack features tons of compartments — including a laptop sleeve — and can even stand up on its own. Its padded shoulder straps offer comfort and it also has two grab handles on top making it convenient to open and provide a balanced carry. It’s also endorsed by the American Chiropractic Association thanks to its comfortable FlexVent suspension system.<a class="view-deal button" href="https://www.rei.com/product/165715/the-north-face-jester-daypack" target="_blank" rel="nofollow" data-dimension112="fcbd0f00-d216-11f1-a965-bd9bde873bdf" data-action="Deal Block" data-label="Jester Daypack" data-dimension48="Jester Daypack" data-dimension25="$44">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd0f6e-d216-11f1-b195-b36487b322c8" data-action="Deal Block" data-label="Sunriser Hoodie (Men's)" data-dimension48="Sunriser Hoodie (Men's)" data-dimension25="$56" href="https://www.thenorthface.com/en-us/p/mens/mens-tops/mens-active-tops-224210/mens-sunriser-hoodie-NF0A8BN8?color=2EL" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:688px;"><p class="vanilla-image-block" style="padding-top:116.28%;"><img id="3JpsW9Lw9CUbH56rbBPUh4" name="sunriser hoodie" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3JpsW9Lw9CUbH56rbBPUh4-1920-80.jpg" mos="" align="middle" fullscreen="" width="688" height="800" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.thenorthface.com/en-us/p/mens/mens-tops/mens-active-tops-224210/mens-sunriser-hoodie-NF0A8BN8?color=2EL" target="_blank" rel="nofollow" data-dimension112="fcbd0f6e-d216-11f1-b195-b36487b322c8" data-action="Deal Block" data-label="Sunriser Hoodie (Men's)" data-dimension48="Sunriser Hoodie (Men's)" data-dimension25="$56">Sunriser Hoodie (Men's): was $80 now $56</a></strong><br />This attractive hoodie has more going for it than just looks, thanks to The North Face’s Lightrange finish, which provides UPF protection, anti-odor technology, and moisture-wicking properties. It also has reflective elements on the chest and back, making it a great pick for evening runners.<a class="view-deal button" href="https://www.thenorthface.com/en-us/p/mens/mens-tops/mens-active-tops-224210/mens-sunriser-hoodie-NF0A8BN8?color=2EL" target="_blank" rel="nofollow" data-dimension112="fcbd0f6e-d216-11f1-b195-b36487b322c8" data-action="Deal Block" data-label="Sunriser Hoodie (Men's)" data-dimension48="Sunriser Hoodie (Men's)" data-dimension25="$56">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd0fdc-d216-11f1-ab39-3f5c93417ad0" data-action="Deal Block" data-label="Jester Everyday Laptop Backpack" data-dimension48="Jester Everyday Laptop Backpack" data-dimension25="$59" href="https://www.amazon.com/North-Face-Womens-Everyday-Backpack/dp/B0CNB261KH?" 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:116.35%;"><img id="JiduFGLLchFPwftiHi7DLN" name="" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/JiduFGLLchFPwftiHi7DLN-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="790" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/North-Face-Womens-Everyday-Backpack/dp/B0CNB261KH?" target="_blank" rel="nofollow" data-dimension112="fcbd0fdc-d216-11f1-ab39-3f5c93417ad0" data-action="Deal Block" data-label="Jester Everyday Laptop Backpack" data-dimension48="Jester Everyday Laptop Backpack" data-dimension25="$59">Jester Everyday Laptop Backpack: was $90 now $59</a></strong><br />The North Face Jester backpack is the ideal campus backpack. It has a 30 liter capacity, a padded 15-inch laptop sleeve, and a front organization pocket with mesh water bottle holders. <a class="view-deal button" href="https://www.amazon.com/North-Face-Womens-Everyday-Backpack/dp/B0CNB261KH?" target="_blank" rel="nofollow" data-dimension112="fcbd0fdc-d216-11f1-ab39-3f5c93417ad0" data-action="Deal Block" data-label="Jester Everyday Laptop Backpack" data-dimension48="Jester Everyday Laptop Backpack" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd104a-d216-11f1-a908-2d7a86d54645" data-action="Deal Block" data-label="DotKnit Thermal ¼-Zip (Women's)" data-dimension48="DotKnit Thermal ¼-Zip (Women's)" data-dimension25="$64" href="https://www.rei.com/product/254013/the-north-face-dotknit-thermal-quarter-zip-pullover-womens?color=MIDNIGHT%2520PETROL" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:576px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="JkvuGYs7dyyBgbeoS9VyUF" name="The North Face dotknot" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/JkvuGYs7dyyBgbeoS9VyUF-1920-80.jpg" mos="" align="middle" fullscreen="" width="576" height="576" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/254013/the-north-face-dotknit-thermal-quarter-zip-pullover-womens?color=MIDNIGHT%2520PETROL" target="_blank" rel="nofollow" data-dimension112="fcbd104a-d216-11f1-a908-2d7a86d54645" data-action="Deal Block" data-label="DotKnit Thermal ¼-Zip (Women's)" data-dimension48="DotKnit Thermal ¼-Zip (Women's)" data-dimension25="$64">DotKnit Thermal ¼-Zip (Women's): was $90 now $64</a></strong><br />If you're a runner, you need this ¼-zip for the colder months. Not only does it help regulate body temperature with its innovative insulating fabric, it also actively moves moisture away from the body.<a class="view-deal button" href="https://www.rei.com/product/254013/the-north-face-dotknit-thermal-quarter-zip-pullover-womens?color=MIDNIGHT%2520PETROL" target="_blank" rel="nofollow" data-dimension112="fcbd104a-d216-11f1-a908-2d7a86d54645" data-action="Deal Block" data-label="DotKnit Thermal ¼-Zip (Women's)" data-dimension48="DotKnit Thermal ¼-Zip (Women's)" data-dimension25="$64">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd10b8-d216-11f1-b523-4bdef0e8ca60" data-action="Deal Block" data-label="Osito Lux Jacket (Women's)" data-dimension48="Osito Lux Jacket (Women's)" data-dimension25="$65" href="https://www.rei.com/product/250475/the-north-face-osito-lux-jacket-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1290px;"><p class="vanilla-image-block" style="padding-top:116.28%;"><img id="MZdvPZM2QPb9UsJtviZ5GJ" name="Osito Lux Jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/MZdvPZM2QPb9UsJtviZ5GJ-1920-80.jpg" mos="" align="middle" fullscreen="" width="1290" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/250475/the-north-face-osito-lux-jacket-womens" target="_blank" rel="nofollow" data-dimension112="fcbd10b8-d216-11f1-b523-4bdef0e8ca60" data-action="Deal Block" data-label="Osito Lux Jacket (Women's)" data-dimension48="Osito Lux Jacket (Women's)" data-dimension25="$65">Osito Lux Jacket (Women's): was $130 now $65</a></strong><br />The super soft Osito Jacket is made with a supersoft high-pile fleece and provides instant, lightweight warmth. It has a rib-knit collar, hem and cuffs for better warmth retention in chilly weather.<a class="view-deal button" href="https://www.rei.com/product/250475/the-north-face-osito-lux-jacket-womens" target="_blank" rel="nofollow" data-dimension112="fcbd10b8-d216-11f1-b523-4bdef0e8ca60" data-action="Deal Block" data-label="Osito Lux Jacket (Women's)" data-dimension48="Osito Lux Jacket (Women's)" data-dimension25="$65">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd1180-d216-11f1-8860-8be4a04140ad" data-action="Deal Block" data-label="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension48="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension25="$74" href="https://www.rei.com/product/C00697/the-north-face-yumiori-off-peak-full-zip-jacket-womens" 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="vamU4Ky2CB4QQda8nfrvm4" name="the north face yumiori jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vamU4Ky2CB4QQda8nfrvm4-1920-80.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C00697/the-north-face-yumiori-off-peak-full-zip-jacket-womens" target="_blank" rel="nofollow" data-dimension112="fcbd1180-d216-11f1-8860-8be4a04140ad" data-action="Deal Block" data-label="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension48="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension25="$74">Yumiori Off Peak Full-Zip Jacket - Women's: was $150 now $74</a></strong><br />The North Face's Yumiori fleece is a perfect hiking-slash-everyday fleece. Smartphones fit snugly into the chest pocket, one zipper even doubles as a hair tie, and it's finished with durable water repellent.<a class="view-deal button" href="https://www.rei.com/product/C00697/the-north-face-yumiori-off-peak-full-zip-jacket-womens" target="_blank" rel="nofollow" data-dimension112="fcbd1180-d216-11f1-8860-8be4a04140ad" data-action="Deal Block" data-label="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension48="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension25="$74">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd1248-d216-11f1-8850-a78ea49d6b96" data-action="Deal Block" data-label="Kikash Wind Jacket (Women's)" data-dimension48="Kikash Wind Jacket (Women's)" data-dimension25="$75" href="https://www.rei.com/product/254048/the-north-face-kikash-wind-jacket-womens" 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="euVM6xCmm2F8CfG6fPp57T" name="Kikash jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/euVM6xCmm2F8CfG6fPp57T-1920-80.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/254048/the-north-face-kikash-wind-jacket-womens" target="_blank" rel="nofollow" data-dimension112="fcbd1248-d216-11f1-8850-a78ea49d6b96" data-action="Deal Block" data-label="Kikash Wind Jacket (Women's)" data-dimension48="Kikash Wind Jacket (Women's)" data-dimension25="$75">Kikash Wind Jacket (Women's): was $150 now $75</a></strong><br />The Kikash Wind Jacket is built for those days when the wind won't quit. The durable nylon fabric shrugs off mountain gusts while keeping you mobile, and reflective details add crucial visibility for early starts or late finishes. The secure zip pockets and snug elastic hem make it a reliable companion for unpredictable conditions.<a class="view-deal button" href="https://www.rei.com/product/254048/the-north-face-kikash-wind-jacket-womens" target="_blank" rel="nofollow" data-dimension112="fcbd1248-d216-11f1-8850-a78ea49d6b96" data-action="Deal Block" data-label="Kikash Wind Jacket (Women's)" data-dimension48="Kikash Wind Jacket (Women's)" data-dimension25="$75">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd13d8-d216-11f1-a8bb-b763a0088eca" data-action="Deal Block" data-label="TNF Performance Fleece 1/4 Zip Jacket (Women's)" data-dimension48="TNF Performance Fleece 1/4 Zip Jacket (Women's)" data-dimension25="$80" href="https://www.amazon.com/dp/B0FX8Z9VH4?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:662px;"><p class="vanilla-image-block" style="padding-top:226.59%;"><img id="4xm4Hfhke6ZnYYKS66BiEd" name="TNF Performance Fleece 1/4 Zip Jacket (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4xm4Hfhke6ZnYYKS66BiEd-1920-80.jpg" mos="" align="middle" fullscreen="" width="662" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0FX8Z9VH4?" target="_blank" rel="nofollow" data-dimension112="fcbd13d8-d216-11f1-a8bb-b763a0088eca" data-action="Deal Block" data-label="TNF Performance Fleece 1/4 Zip Jacket (Women's)" data-dimension48="TNF Performance Fleece 1/4 Zip Jacket (Women's)" data-dimension25="$80">TNF Performance Fleece 1/4 Zip Jacket (Women's): was $90 now $80</a></strong><br />It's hard to say no to this cozy fleece. It's made of soft polyester fleece, with an athletic look and lightweight feel. Make sure to grab one to layer up when temperatures drop on crisp fall days.<a class="view-deal button" href="https://www.amazon.com/dp/B0FX8Z9VH4?" target="_blank" rel="nofollow" data-dimension112="fcbd13d8-d216-11f1-a8bb-b763a0088eca" data-action="Deal Block" data-label="TNF Performance Fleece 1/4 Zip Jacket (Women's)" data-dimension48="TNF Performance Fleece 1/4 Zip Jacket (Women's)" data-dimension25="$80">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd1446-d216-11f1-8253-5325d17d1fdd" data-action="Deal Block" data-label="Antora Jacket (Women's)" data-dimension48="Antora Jacket (Women's)" data-dimension25="$91" href="https://www.amazon.com/North-Face-Waterproof-Windproof-Adjustable/dp/B0F97WG8SQ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:731px;"><p class="vanilla-image-block" style="padding-top:205.20%;"><img id="bN5BuTC38YdrnSkcwmxwpg" name="Antora Jacket (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bN5BuTC38YdrnSkcwmxwpg-1920-80.jpg" mos="" align="middle" fullscreen="" width="731" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/North-Face-Waterproof-Windproof-Adjustable/dp/B0F97WG8SQ" target="_blank" rel="nofollow" data-dimension112="fcbd1446-d216-11f1-8253-5325d17d1fdd" data-action="Deal Block" data-label="Antora Jacket (Women's)" data-dimension48="Antora Jacket (Women's)" data-dimension25="$91">Antora Jacket (Women's): was $130 now $91</a></strong><br />$91 is a great deal for this lightweight, weather-resistant shell. A core piece of outerwear no one should leave home without, the Antora Jacket boasts impressive rain-repellent capabilities. A drawstring-adjustable hood provides extra H2O protection, while a storm flap protects the main zipper from seepage during downpours. More importantly, as far as rain shells go, few can match the style factor of the Antora. <a class="view-deal button" href="https://www.amazon.com/North-Face-Waterproof-Windproof-Adjustable/dp/B0F97WG8SQ" target="_blank" rel="nofollow" data-dimension112="fcbd1446-d216-11f1-8253-5325d17d1fdd" data-action="Deal Block" data-label="Antora Jacket (Women's)" data-dimension48="Antora Jacket (Women's)" data-dimension25="$91">View Deal</a></p></div><div class="product"><a data-dimension112="fcbd14b4-d216-11f1-b60b-737447380189" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$135" href="https://www.amazon.com/dp/B0F1WYVHWW?" 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:187.78%;"><img id="jLN4YbW223nKsxQxPVPWZR" name="TNF jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jLN4YbW223nKsxQxPVPWZR-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1275" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0F1WYVHWW?" target="_blank" rel="nofollow" data-dimension112="fcbd14b4-d216-11f1-b60b-737447380189" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$135">Aconcagua 3 Jacket (Men's): was $200 now $135</a></strong><br />This lightweight puffer blends recycled down with synthetic insulation for maximum warmth and weather resistance in a tidy, easy-to-stow package. Zonal sheet insulation and a water-repellant finish round out the feature set.<a class="view-deal button" href="https://www.amazon.com/dp/B0F1WYVHWW?" target="_blank" rel="nofollow" data-dimension112="fcbd14b4-d216-11f1-b60b-737447380189" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$135">View Deal</a></p></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Asics running shoes are up to 56% off — 21 best deals to set PRs this fall ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Asics running shoes are some of the most popular on the market — and some of the <a href="https://www.tomsguide.com/best-picks/best-running-shoes">best running shoes</a> we've tested, too. If you're hoping to improve your PRs this fall, make sure to check out these Asics running shoe deals at Amazon.</p><p>My favorite deal right now is the <a href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Cobalt/dp/B0F63X6TCG/" target="_blank" rel="nofollow">Asics Novablast 5 on sale from $129</a>. It's a previous winner on our list of the best running shoes, and it's still a great buy today because of its comfortable, smooth feel.</p><p><strong>Note: </strong>Prices can vary depending on the size and color you choose — check out any different color options in your size to find the best deals.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links </span></h3><ul><li><a href="https://www.amazon.com/stores/ASICS/page/3D51EC88-4320-4F70-8CAF-9E7C77D723E2" target="_blank" rel="nofollow"><strong>shop all Asics deals on Amazon</strong></a></li><li><strong>Asics Gel-Kayano 30 (Women's): </strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow"><strong>was $160 now from $69</strong></a></li><li><strong>Asics Versablast 4 Running Shoes (Women's): </strong><a href="https://www.amazon.com/ASICS-Womens-VERSABLAST-Running-Shoes/dp/B0F5CSWHS6" target="_blank" rel="nofollow"><strong>was $80 now from $69</strong></a></li><li><strong>Asics Novablast 5 (Men's): </strong><a href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow"><strong>was $160 now from $129</strong></a></li><li><strong>Asics Superblast 2 (Unisex): </strong><a href="https://www.amazon.com/ASICS-Unisex-SUPERBLAST-EKIDEN-Running/dp/B0FFKVZV1D" target="_blank" rel="nofollow"><strong>was $199 now $149</strong></a></li></ul><h3 class="article-body__section" id="section-asics-shoes"><span>Asics Shoes</span></h3><div class="product"><a data-dimension112="20582a14-d382-11f1-ae82-0397e4ad8870" data-action="Deal Block" data-label="Gel-Contend 9 (Men's)" data-dimension48="Gel-Contend 9 (Men's)" data-dimension25="$54" href="https://www.amazon.com/ASICS-Gel-Contend-Running-Shoes-Carrier/dp/B0F6NQLR41" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:44.38%;"><img id="aWiLt2wFJJJbFXnkXMA5bD" name="Gel-Contend 9 (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/aWiLt2wFJJJbFXnkXMA5bD-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="513" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Gel-Contend-Running-Shoes-Carrier/dp/B0F6NQLR41" target="_blank" rel="nofollow" data-dimension112="20582a14-d382-11f1-ae82-0397e4ad8870" data-action="Deal Block" data-label="Gel-Contend 9 (Men's)" data-dimension48="Gel-Contend 9 (Men's)" data-dimension25="$54">Gel-Contend 9 (Men's): was $75 now $54</a></strong><br />The ASICS GEL-Contend 9 is a great all around shoe with a breathable upper that moves with your foot and has extra cushioning to keep things soft underfoot. It’s ideal if you’re new to running or want a budget-friendly shoe that feels supportive for workouts, easy miles or long walks.<a class="view-deal button" href="https://www.amazon.com/ASICS-Gel-Contend-Running-Shoes-Carrier/dp/B0F6NQLR41" target="_blank" rel="nofollow" data-dimension112="20582a14-d382-11f1-ae82-0397e4ad8870" data-action="Deal Block" data-label="Gel-Contend 9 (Men's)" data-dimension48="Gel-Contend 9 (Men's)" data-dimension25="$54">View Deal</a></p></div><div class="product"><a data-dimension112="a02025e2-d1f4-11f1-a79a-cb46f224f8bf" data-action="Deal Block" data-label="Gel-Venture 9 Running Shoes (Men's)" data-dimension48="Gel-Venture 9 Running Shoes (Men's)" data-dimension25="$59" href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Sheet/dp/B0B47YVK12" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1157px;"><p class="vanilla-image-block" style="padding-top:45.55%;"><img id="FGGxuYvWwdm7YU6PMbr6B9" name="Gel-Venture 9 Running Shoes (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/FGGxuYvWwdm7YU6PMbr6B9-1920-80.jpg" mos="" align="middle" fullscreen="" width="1157" height="527" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Sheet/dp/B0B47YVK12" target="_blank" rel="nofollow" data-dimension112="a02025e2-d1f4-11f1-a79a-cb46f224f8bf" data-action="Deal Block" data-label="Gel-Venture 9 Running Shoes (Men's)" data-dimension48="Gel-Venture 9 Running Shoes (Men's)" data-dimension25="$59">Gel-Venture 9 Running Shoes (Men's): was $80 now $59</a></strong><br />Score the Asics Gel Venture 9 Running Shoes on sale from $59 at Amazon. These shoes are excellent for trail runs, with a traction pattern designed to support you on outdoor terrain. They also feature Rearfoot GEL to absorb impact and super-soft AMPLIFOAM cushioning.<a class="view-deal button" href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Sheet/dp/B0B47YVK12" target="_blank" rel="nofollow" data-dimension112="a02025e2-d1f4-11f1-a79a-cb46f224f8bf" data-action="Deal Block" data-label="Gel-Venture 9 Running Shoes (Men's)" data-dimension48="Gel-Venture 9 Running Shoes (Men's)" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="ce446306-d448-11f1-8ac3-1728603cf6ec" data-action="Deal Block" data-label="Game FlyteFoam Pickleball Shoes (Women's)" data-dimension48="Game FlyteFoam Pickleball Shoes (Women's)" data-dimension25="$59" href="https://www.amazon.com/ASICS-Womens-Pickleball-Tennis-Purple/dp/B0DP1D8RBK" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:47.49%;"><img id="PQguZuXt8VG966JUtq9TAS" name="Game FlyteFoam Pickleball Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/PQguZuXt8VG966JUtq9TAS-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="549" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Pickleball-Tennis-Purple/dp/B0DP1D8RBK" target="_blank" rel="nofollow" data-dimension112="ce446306-d448-11f1-8ac3-1728603cf6ec" data-action="Deal Block" data-label="Game FlyteFoam Pickleball Shoes (Women's)" data-dimension48="Game FlyteFoam Pickleball Shoes (Women's)" data-dimension25="$59">Game FlyteFoam Pickleball Shoes (Women's): was $90 now $59</a></strong><br />Improve your game with the Asics Game FlyteFoam Pickleball shoes! They're designed to have extra ventilation and flexibility to move with you and keep your feet from overheating.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Pickleball-Tennis-Purple/dp/B0DP1D8RBK" target="_blank" rel="nofollow" data-dimension112="ce446306-d448-11f1-8ac3-1728603cf6ec" data-action="Deal Block" data-label="Game FlyteFoam Pickleball Shoes (Women's)" data-dimension48="Game FlyteFoam Pickleball Shoes (Women's)" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="a02026b4-d1f4-11f1-bdf6-134aa1c2f7f4" data-action="Deal Block" data-label="Upcourt 6 Volleyball Shoes (Women's)" data-dimension48="Upcourt 6 Volleyball Shoes (Women's)" data-dimension25="$64" href="https://www.amazon.com/ASICS-Womens-Upcourt-Volleyball-Shoes/dp/B0GXCKGNNZ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1164px;"><p class="vanilla-image-block" style="padding-top:43.47%;"><img id="GzQK5bL8yXHCDELcBXQfqK" name="Upcourt 6 Volleyball Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/GzQK5bL8yXHCDELcBXQfqK-1920-80.jpg" mos="" align="middle" fullscreen="" width="1164" height="506" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Upcourt-Volleyball-Shoes/dp/B0GXCKGNNZ" target="_blank" rel="nofollow" data-dimension112="a02026b4-d1f4-11f1-bdf6-134aa1c2f7f4" data-action="Deal Block" data-label="Upcourt 6 Volleyball Shoes (Women's)" data-dimension48="Upcourt 6 Volleyball Shoes (Women's)" data-dimension25="$64">Upcourt 6 Volleyball Shoes (Women's): was $75 now $64</a></strong><br />Put your best foot forward on the volleyball court with the Asics Upcourt 6. These have a lightweight and flexible design, paired with soft and breathable mesh paneling across the upper. <a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Upcourt-Volleyball-Shoes/dp/B0GXCKGNNZ" target="_blank" rel="nofollow" data-dimension112="a02026b4-d1f4-11f1-bdf6-134aa1c2f7f4" data-action="Deal Block" data-label="Upcourt 6 Volleyball Shoes (Women's)" data-dimension48="Upcourt 6 Volleyball Shoes (Women's)" data-dimension25="$64">View Deal</a></p></div><div class="product"><a data-dimension112="a020279a-d1f4-11f1-947a-b3fde5bcce92" data-action="Deal Block" data-label="Women's Novablast 4" data-dimension48="Women's Novablast 4" data-dimension25="$67" href="https://www.amazon.com/ASICS-Womens-NOVABLAST-Running-Expanse/dp/B0CFP3J6RB" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1200px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="wMYSVC2325TPeXMt7TJ9t3" name="Asics Novablast 4" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/wMYSVC2325TPeXMt7TJ9t3-1920-80.jpg" mos="" align="middle" fullscreen="" width="1200" height="1200" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-NOVABLAST-Running-Expanse/dp/B0CFP3J6RB" target="_blank" rel="nofollow" data-dimension112="a020279a-d1f4-11f1-947a-b3fde5bcce92" data-action="Deal Block" data-label="Women's Novablast 4" data-dimension48="Women's Novablast 4" data-dimension25="$67">Women's Novablast 4: was $140 now $67</a></strong><br />Old but gold. While the Novablast 6 is now available, the Novablast 4 is beloved by the Tom's Guide team — especially our Fitness Editor Jane McGuire, who wrote: "I've run over 100 miles in this shoe, and it's still one I reach for when I'm heading out for a long run."<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-NOVABLAST-Running-Expanse/dp/B0CFP3J6RB" target="_blank" rel="nofollow" data-dimension112="a020279a-d1f4-11f1-947a-b3fde5bcce92" data-action="Deal Block" data-label="Women's Novablast 4" data-dimension48="Women's Novablast 4" data-dimension25="$67">View Deal</a></p></div><div class="product"><a data-dimension112="20582af0-d382-11f1-834e-cfb2699195da" data-action="Deal Block" data-label="Gel-Venture 10 (Women's)" data-dimension48="Gel-Venture 10 (Women's)" data-dimension25="$67" href="https://www.amazon.com/ASICS-Womens-Gel-Venture-Running-Gravel/dp/B0D461PLVS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:50.95%;"><img id="vp24xzcYprCWGX65bT4nnN" name="Gel-Venture 10 (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vp24xzcYprCWGX65bT4nnN-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="589" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Venture-Running-Gravel/dp/B0D461PLVS" target="_blank" rel="nofollow" data-dimension112="20582af0-d382-11f1-834e-cfb2699195da" data-action="Deal Block" data-label="Gel-Venture 10 (Women's)" data-dimension48="Gel-Venture 10 (Women's)" data-dimension25="$67">Gel-Venture 10 (Women's): was $80 now $67</a></strong><br />These shoes are excellent for runs, with a traction pattern designed to support you on outdoor terrain. They also feature Rearfoot GEL to absorb impact and super-soft AMPLIFOAM cushioning.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Gel-Venture-Running-Gravel/dp/B0D461PLVS" target="_blank" rel="nofollow" data-dimension112="20582af0-d382-11f1-834e-cfb2699195da" data-action="Deal Block" data-label="Gel-Venture 10 (Women's)" data-dimension48="Gel-Venture 10 (Women's)" data-dimension25="$67">View Deal</a></p></div><div class="product"><a data-dimension112="ce4463f6-d448-11f1-8a89-3b432f5e0f1b" data-action="Deal Block" data-label="Gel-Venture 11 Trail (Men's)" data-dimension48="Gel-Venture 11 Trail (Men's)" data-dimension25="$69" href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Steel/dp/B0FV7BC2RR" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1146px;"><p class="vanilla-image-block" style="padding-top:75.04%;"><img id="44i7uWA8WvTqRemkvKZpV6" name="Gel-Venture 11" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/44i7uWA8WvTqRemkvKZpV6-1920-80.jpg" mos="" align="middle" fullscreen="" width="1146" height="860" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Steel/dp/B0FV7BC2RR" target="_blank" rel="nofollow" data-dimension112="ce4463f6-d448-11f1-8a89-3b432f5e0f1b" data-action="Deal Block" data-label="Gel-Venture 11 Trail (Men's)" data-dimension48="Gel-Venture 11 Trail (Men's)" data-dimension25="$69">Gel-Venture 11 Trail (Men's): was $90 now $69</a></strong><br />The Asics Gel-Venture 11 are designed for everyday runs and hitting the trails! They have Amplifoam Plus midsole cushioning on board, and a 2mm higher stack height — 2mm of extra softness to absorb impact and keep you comfortable for hours.<a class="view-deal button" href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Steel/dp/B0FV7BC2RR" target="_blank" rel="nofollow" data-dimension112="ce4463f6-d448-11f1-8a89-3b432f5e0f1b" data-action="Deal Block" data-label="Gel-Venture 11 Trail (Men's)" data-dimension48="Gel-Venture 11 Trail (Men's)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="a0202876-d1f4-11f1-b807-b516cc2e03a1" data-action="Deal Block" data-label="Gel-Kayano 30 (Women's)" data-dimension48="Gel-Kayano 30 (Women's)" data-dimension25="$69" href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1160px;"><p class="vanilla-image-block" style="padding-top:46.29%;"><img id="iHsvdtLnzyeWEyCZV8HBYe" name="Gel-Kayano 30 (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/iHsvdtLnzyeWEyCZV8HBYe-1920-80.jpg" mos="" align="middle" fullscreen="" width="1160" height="537" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow" data-dimension112="a0202876-d1f4-11f1-b807-b516cc2e03a1" data-action="Deal Block" data-label="Gel-Kayano 30 (Women's)" data-dimension48="Gel-Kayano 30 (Women's)" data-dimension25="$69">Gel-Kayano 30 (Women's): was $160 now $69</a></strong><br />The Gel Kayano 30 running shoes are an older model, but they're amazingly cheap with 56% off. They're designed to provide advanced stability and soft cushioning for neutral runners and overpronators alike. Our Deals Editor-in-Chief, Louis Ramirez, wrote: "I've been using these shoes for almost two years now. (I loved them so much I bought a second pair months after buying my first pair). I find that they're great for casual runs on the treadmill, HIIT sessions, and long distance running outdoors."<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow" data-dimension112="a0202876-d1f4-11f1-b807-b516cc2e03a1" data-action="Deal Block" data-label="Gel-Kayano 30 (Women's)" data-dimension48="Gel-Kayano 30 (Women's)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="a0202952-d1f4-11f1-ac11-659affe7682f" data-action="Deal Block" data-label="Versablast 4 Running Shoes (Women's)" data-dimension48="Versablast 4 Running Shoes (Women's)" data-dimension25="$69" href="https://www.amazon.com/ASICS-Womens-VERSABLAST-Running-Shoes/dp/B0F5CSWHS6" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:46.97%;"><img id="aXzwegkSgySzw9j2Pjj42L" name="Versablast 4 Running Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/aXzwegkSgySzw9j2Pjj42L-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="543" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-VERSABLAST-Running-Shoes/dp/B0F5CSWHS6" target="_blank" rel="nofollow" data-dimension112="a0202952-d1f4-11f1-ac11-659affe7682f" data-action="Deal Block" data-label="Versablast 4 Running Shoes (Women's)" data-dimension48="Versablast 4 Running Shoes (Women's)" data-dimension25="$69">Versablast 4 Running Shoes (Women's): was $80 now $69</a></strong><br />Packed with Amplifoam+ cushioning, the Asics Versablast 4 are built to be both soft and responsive — and are now a steal with this discount. The Cream/Hazy Lilac colorway is gorgeous, too.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-VERSABLAST-Running-Shoes/dp/B0F5CSWHS6" target="_blank" rel="nofollow" data-dimension112="a0202952-d1f4-11f1-ac11-659affe7682f" data-action="Deal Block" data-label="Versablast 4 Running Shoes (Women's)" data-dimension48="Versablast 4 Running Shoes (Women's)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="a0202a10-d1f4-11f1-b27a-1f9e9608d731" data-action="Deal Block" data-label="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension48="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension25="$69" href="https://www.amazon.com/ASICS-Gel-Contend-Running-Shoes-Black/dp/B0GY9NML2X" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:45.42%;"><img id="yyx3Rc6DdUotj8NTEwFwLa" name="Gel-Contend 10 Road Running Shoes (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/yyx3Rc6DdUotj8NTEwFwLa-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="525" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Gel-Contend-Running-Shoes-Black/dp/B0GY9NML2X" target="_blank" rel="nofollow" data-dimension112="a0202a10-d1f4-11f1-b27a-1f9e9608d731" data-action="Deal Block" data-label="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension48="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension25="$69">Gel-Contend 10 Road Running Shoes (Men's): was $80 now $69</a></strong><br />The 10th iteration of Asics' budget-friendly road running shoes have dropped in price! They feature Amplifoam+ cushioning to support your runs and have a lightweight and breathable mesh upper.<a class="view-deal button" href="https://www.amazon.com/ASICS-Gel-Contend-Running-Shoes-Black/dp/B0GY9NML2X" target="_blank" rel="nofollow" data-dimension112="a0202a10-d1f4-11f1-b27a-1f9e9608d731" data-action="Deal Block" data-label="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension48="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="ce4464d2-d448-11f1-9719-8158578fad74" data-action="Deal Block" data-label="Gel-Pulse 16 (Women's)" data-dimension48="Gel-Pulse 16 (Women's)" data-dimension25="$73" href="https://www.amazon.com/ASICS-Womens-Gel-Pulse-Running-Midnight/dp/B0D462MWTB" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:48.88%;"><img id="Woj2dkTQp2a9nuWs5nFuDg" name="Gel-Pulse 16 (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Woj2dkTQp2a9nuWs5nFuDg-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="565" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Pulse-Running-Midnight/dp/B0D462MWTB" target="_blank" rel="nofollow" data-dimension112="ce4464d2-d448-11f1-9719-8158578fad74" data-action="Deal Block" data-label="Gel-Pulse 16 (Women's)" data-dimension48="Gel-Pulse 16 (Women's)" data-dimension25="$73">Gel-Pulse 16 (Women's): was $100 now $73</a></strong><br />This is one of the cheaper Asics running shoe deals you'll find, so this shoe is definitely worth a purchase. However, stock is limited, so act fast! It's regarded as a comfy and versatile sneaker that suits neutral runners in particular.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Gel-Pulse-Running-Midnight/dp/B0D462MWTB" target="_blank" rel="nofollow" data-dimension112="ce4464d2-d448-11f1-9719-8158578fad74" data-action="Deal Block" data-label="Gel-Pulse 16 (Women's)" data-dimension48="Gel-Pulse 16 (Women's)" data-dimension25="$73">View Deal</a></p></div><div class="product"><a data-dimension112="a0202a74-d1f4-11f1-b2f8-7183f742df15" data-action="Deal Block" data-label="Gel-Excite 11 (Women's)" data-dimension48="Gel-Excite 11 (Women's)" data-dimension25="$74" href="https://www.amazon.com/ASICS-Womens-Gel-Excite-Running-MORGANITE/dp/B0F64HHL33/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1163px;"><p class="vanilla-image-block" style="padding-top:58.73%;"><img id="ApA8TRKTowTCiYpEXd3LDK" name="gel excite" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ApA8TRKTowTCiYpEXd3LDK-1920-80.jpg" mos="" align="middle" fullscreen="" width="1163" height="683" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Excite-Running-MORGANITE/dp/B0F64HHL33/" target="_blank" rel="nofollow" data-dimension112="a0202a74-d1f4-11f1-b2f8-7183f742df15" data-action="Deal Block" data-label="Gel-Excite 11 (Women's)" data-dimension48="Gel-Excite 11 (Women's)" data-dimension25="$74">Gel-Excite 11 (Women's): was $90 now $74</a></strong><br />The Gel-Excite 11 are now on sale for a discount, bringing their price under $75. Designed for running and fitness, it brings a higher stack and a super soft and comfortable feel underfoot. The reflective details are also handy if you're working out in low light.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Gel-Excite-Running-MORGANITE/dp/B0F64HHL33/" target="_blank" rel="nofollow" data-dimension112="a0202a74-d1f4-11f1-b2f8-7183f742df15" data-action="Deal Block" data-label="Gel-Excite 11 (Women's)" data-dimension48="Gel-Excite 11 (Women's)" data-dimension25="$74">View Deal</a></p></div><div class="product"><a data-dimension112="a0202ad8-d1f4-11f1-8e40-9fd6e825c988" data-action="Deal Block" data-label="GT-1000 14 Running Shoes (Women's)" data-dimension48="GT-1000 14 Running Shoes (Women's)" data-dimension25="$79" href="https://www.amazon.com/ASICS-Womens-GT-1000-Running-Shoes/dp/B0F5YXB9D6/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:49.57%;"><img id="ep5SNjswGLfrwX5LzXTK85" name="GT-1000 14 Running Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ep5SNjswGLfrwX5LzXTK85-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="573" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-GT-1000-Running-Shoes/dp/B0F5YXB9D6/" target="_blank" rel="nofollow" data-dimension112="a0202ad8-d1f4-11f1-8e40-9fd6e825c988" data-action="Deal Block" data-label="GT-1000 14 Running Shoes (Women's)" data-dimension48="GT-1000 14 Running Shoes (Women's)" data-dimension25="$79">GT-1000 14 Running Shoes (Women's): was $110 now $79</a></strong><br />Asics' affordable series of GT-1000 running shoes are even better with a discount. The 14th iteration of the shoe features a 3D guidance system built in to keep you stable on your feet as you run! <a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-GT-1000-Running-Shoes/dp/B0F5YXB9D6/" target="_blank" rel="nofollow" data-dimension112="a0202ad8-d1f4-11f1-8e40-9fd6e825c988" data-action="Deal Block" data-label="GT-1000 14 Running Shoes (Women's)" data-dimension48="GT-1000 14 Running Shoes (Women's)" data-dimension25="$79">View Deal</a></p></div><div class="product"><a data-dimension112="a0202b3c-d1f4-11f1-a461-b7fff4f10045" data-action="Deal Block" data-label="Glideride Max (Men's)" data-dimension48="Glideride Max (Men's)" data-dimension25="$99" href="https://www.amazon.com/ASICS-GLIDERIDE-Running-Monument-Vanilla/dp/B0CT9HG8TB" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1157px;"><p class="vanilla-image-block" style="padding-top:50.91%;"><img id="ur2nzvnBf49fo9rfEakkpK" name="Glideride Max (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ur2nzvnBf49fo9rfEakkpK-1920-80.jpg" mos="" align="middle" fullscreen="" width="1157" height="589" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-GLIDERIDE-Running-Monument-Vanilla/dp/B0CT9HG8TB" target="_blank" rel="nofollow" data-dimension112="a0202b3c-d1f4-11f1-a461-b7fff4f10045" data-action="Deal Block" data-label="Glideride Max (Men's)" data-dimension48="Glideride Max (Men's)" data-dimension25="$99">Glideride Max (Men's): was $170 now $99</a></strong><br />At 42% off, the Asics Glideride are a steal. These come with GuideSole tech to help you save energy, keeping you going for longer. You also get FF Blast Max cushioning for a lightweight, soft feel.<a class="view-deal button" href="https://www.amazon.com/ASICS-GLIDERIDE-Running-Monument-Vanilla/dp/B0CT9HG8TB" target="_blank" rel="nofollow" data-dimension112="a0202b3c-d1f4-11f1-a461-b7fff4f10045" data-action="Deal Block" data-label="Glideride Max (Men's)" data-dimension48="Glideride Max (Men's)" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="a0202ba0-d1f4-11f1-94e7-f3067fc0bb7e" data-action="Deal Block" data-label="Gel-Cumulus 27 (Women's)" data-dimension48="Gel-Cumulus 27 (Women's)" data-dimension25="$89" href="https://www.amazon.com/ASICS-Womens-Gel-Cumulus-Running-Shoes/dp/B0D3XQD6XB" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1146px;"><p class="vanilla-image-block" style="padding-top:75.04%;"><img id="vX8LzAvqyUKUxX8CnAhi9b" name="Gel-Cumulus 27 Running Shoes (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vX8LzAvqyUKUxX8CnAhi9b-1920-80.webp" mos="" align="middle" fullscreen="" width="1146" height="860" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Cumulus-Running-Shoes/dp/B0D3XQD6XB" target="_blank" rel="nofollow" data-dimension112="a0202ba0-d1f4-11f1-94e7-f3067fc0bb7e" data-action="Deal Block" data-label="Gel-Cumulus 27 (Women's)" data-dimension48="Gel-Cumulus 27 (Women's)" data-dimension25="$89">Gel-Cumulus 27 (Women's): was $140 now $89</a></strong><br />The Asics Gel-Cumulus 27 often gets overlooked because of the popularity of the Novablast and Gel-Nimbus lines, but it's usually available for less than those shoes, and it's a comfortable, fairly lightweight daily trainer in its own right. We've tested the newer Gel-Cumulus 28 model, and it's not a major update on the 27, so this deal on the older shoe is much better value.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Gel-Cumulus-Running-Shoes/dp/B0D3XQD6XB" target="_blank" rel="nofollow" data-dimension112="a0202ba0-d1f4-11f1-94e7-f3067fc0bb7e" data-action="Deal Block" data-label="Gel-Cumulus 27 (Women's)" data-dimension48="Gel-Cumulus 27 (Women's)" data-dimension25="$89">View Deal</a></p></div><div class="product"><a data-dimension112="a0202bfa-d1f4-11f1-914a-99923e4e1c22" data-action="Deal Block" data-label="Sonicblast Road Running Shoes (Men's)" data-dimension48="Sonicblast Road Running Shoes (Men's)" data-dimension25="$105" href="https://www.amazon.com/Asics-SONICBLAST-Running-Winter-Stillwater/dp/B0DPLQ32YV" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1528px;"><p class="vanilla-image-block" style="padding-top:75.00%;"><img id="rD9sdYvxaqtEV2BgyMfTx" name="Sonicblast" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/rD9sdYvxaqtEV2BgyMfTx-1920-80.jpg" mos="" align="middle" fullscreen="" width="1528" height="1146" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Asics-SONICBLAST-Running-Winter-Stillwater/dp/B0DPLQ32YV" target="_blank" rel="nofollow" data-dimension112="a0202bfa-d1f4-11f1-914a-99923e4e1c22" data-action="Deal Block" data-label="Sonicblast Road Running Shoes (Men's)" data-dimension48="Sonicblast Road Running Shoes (Men's)" data-dimension25="$105">Sonicblast Road Running Shoes (Men's): was $180 now $105</a></strong><br />Suited for both fast runs and everyday training, the Asics Sonicblast are super lightweight and propulsive. There's an Astroplate mechanism to help you shoot forward, as well as FF Blast Max and FF Turbo cushioning for a bouncy feel underfoot.<a class="view-deal button" href="https://www.amazon.com/Asics-SONICBLAST-Running-Winter-Stillwater/dp/B0DPLQ32YV" target="_blank" rel="nofollow" data-dimension112="a0202bfa-d1f4-11f1-914a-99923e4e1c22" data-action="Deal Block" data-label="Sonicblast Road Running Shoes (Men's)" data-dimension48="Sonicblast Road Running Shoes (Men's)" data-dimension25="$105">View Deal</a></p></div><div class="product"><a data-dimension112="a0202c5e-d1f4-11f1-9225-994cdda92eb4" data-action="Deal Block" data-label="Gel-K1011 Sneakers (Men's)" data-dimension48="Gel-K1011 Sneakers (Men's)" data-dimension25="$99" href="https://www.amazon.com/ASICS-Unisex-GEL-K1011-Sportstyle-Shoes/dp/B0GZWDQHQH" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:48.88%;"><img id="BuedRkRo9MvaiVx2pUuCR6" name="Gel-K1011 Sneakers (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/BuedRkRo9MvaiVx2pUuCR6-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="565" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Unisex-GEL-K1011-Sportstyle-Shoes/dp/B0GZWDQHQH" target="_blank" rel="nofollow" data-dimension112="a0202c5e-d1f4-11f1-9225-994cdda92eb4" data-action="Deal Block" data-label="Gel-K1011 Sneakers (Men's)" data-dimension48="Gel-K1011 Sneakers (Men's)" data-dimension25="$99">Gel-K1011 Sneakers (Men's): was $140 now $99</a></strong><br />An iconic design and reliable comfort, what more could you want from a pair of sneakers? It takes cues from some of Asics' best shoes, with Gel-Kayano-inspired panels on the upper and the same midsole tooling system as the Gel-Cumulus 17.<a class="view-deal button" href="https://www.amazon.com/ASICS-Unisex-GEL-K1011-Sportstyle-Shoes/dp/B0GZWDQHQH" target="_blank" rel="nofollow" data-dimension112="a0202c5e-d1f4-11f1-9225-994cdda92eb4" data-action="Deal Block" data-label="Gel-K1011 Sneakers (Men's)" data-dimension48="Gel-K1011 Sneakers (Men's)" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="a0202cc2-d1f4-11f1-acaa-ad86d472601b" data-action="Deal Block" data-label="Fuji Lite 6 Trail Running Shoes (Men's)" data-dimension48="Fuji Lite 6 Trail Running Shoes (Men's)" data-dimension25="$99" href="https://www.amazon.com/ASICS-Trail-Running-Shoes-Aurora/dp/B0F643LGDW" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1146px;"><p class="vanilla-image-block" style="padding-top:75.04%;"><img id="QxFrVRALdPPJaEfNpoi4mP" name="Asics Fuji Lite 6" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/QxFrVRALdPPJaEfNpoi4mP-1920-80.png" mos="" align="middle" fullscreen="" width="1146" height="860" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Trail-Running-Shoes-Aurora/dp/B0F643LGDW" target="_blank" rel="nofollow" data-dimension112="a0202cc2-d1f4-11f1-acaa-ad86d472601b" data-action="Deal Block" data-label="Fuji Lite 6 Trail Running Shoes (Men's)" data-dimension48="Fuji Lite 6 Trail Running Shoes (Men's)" data-dimension25="$99">Fuji Lite 6 Trail Running Shoes (Men's): was $130 now $99</a></strong><br />The Fuji Lite 6 is a lightweight trail-running shoe that offers reliable grip and a speedy, responsive ride for your off-road runs. It's also <a href="https://www.asics.com/us/en-us/fuji-lite-6/p/ANA_1011C086-600.html" target="_blank" rel="nofollow">on sale at Asics</a>. For $99, it's a steal.<a class="view-deal button" href="https://www.amazon.com/ASICS-Trail-Running-Shoes-Aurora/dp/B0F643LGDW" target="_blank" rel="nofollow" data-dimension112="a0202cc2-d1f4-11f1-acaa-ad86d472601b" data-action="Deal Block" data-label="Fuji Lite 6 Trail Running Shoes (Men's)" data-dimension48="Fuji Lite 6 Trail Running Shoes (Men's)" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="a0202d26-d1f4-11f1-bc55-0b91dfbb0b83" data-action="Deal Block" data-label="Novablast 5 (Men's)" data-dimension48="Novablast 5 (Men's)" data-dimension25="$129" href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1166px;"><p class="vanilla-image-block" style="padding-top:48.80%;"><img id="4pk4xESon4iEcQDmd7TqZF" name="Novablast 5 (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4pk4xESon4iEcQDmd7TqZF-1920-80.jpg" mos="" align="middle" fullscreen="" width="1166" height="569" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow" data-dimension112="a0202d26-d1f4-11f1-bc55-0b91dfbb0b83" data-action="Deal Block" data-label="Novablast 5 (Men's)" data-dimension48="Novablast 5 (Men's)" data-dimension25="$129">Novablast 5 (Men's): was $160 now $129</a></strong><br />We voted the Asics Novablast 6 as the <a href="https://www.tomsguide.com/best-picks/best-running-shoes">best running shoes</a> you can buy right now, but before that, the <a href="https://www.tomsguide.com/wellness/running/asics-novablast-5-review">Asics Novablast 5</a> had the top spot. They quickly stood out for their balance of comfort, support and fun, making them a pair of shoes you will actually look forward to running in. They're lightweight, durable and have a soft, springy feel underfoot that helps absorb impact while keeping runs enjoyable.<a class="view-deal button" href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow" data-dimension112="a0202d26-d1f4-11f1-bc55-0b91dfbb0b83" data-action="Deal Block" data-label="Novablast 5 (Men's)" data-dimension48="Novablast 5 (Men's)" data-dimension25="$129">View Deal</a></p></div><div class="product"><a data-dimension112="a0202e0c-d1f4-11f1-b5ca-df3bb42b8d24" data-action="Deal Block" data-label="Superblast 2 (Unisex)" data-dimension48="Superblast 2 (Unisex)" data-dimension25="$149" href="https://www.amazon.com/ASICS-Unisex-SUPERBLAST-EKIDEN-Running/dp/B0FFLKC1J7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1146px;"><p class="vanilla-image-block" style="padding-top:75.04%;"><img id="6Ag4kfoS5FeA9rMnnhtmCF" name="Superblast 2 Ekiden (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/6Ag4kfoS5FeA9rMnnhtmCF-1920-80.webp" mos="" align="middle" fullscreen="" width="1146" height="860" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Unisex-SUPERBLAST-EKIDEN-Running/dp/B0FFLKC1J7" target="_blank" rel="nofollow" data-dimension112="a0202e0c-d1f4-11f1-b5ca-df3bb42b8d24" data-action="Deal Block" data-label="Superblast 2 (Unisex)" data-dimension48="Superblast 2 (Unisex)" data-dimension25="$149">Superblast 2 (Unisex): was $200 now $149</a></strong><br />In our <a href="https://www.tomsguide.com/wellness/running/i-ran-35-miles-in-the-asics-superblast-2-and-its-one-of-the-best-new-shoes-of-2024">Asics Superblast 2 review</a> we said they were one of the best shoes of the year they released. There are newer shoes on the market, but now, you can get them for 25% off. Our testers thought the Superblast 2 was amazing for long runs, and found it to be lightweight and versatile.<a class="view-deal button" href="https://www.amazon.com/ASICS-Unisex-SUPERBLAST-EKIDEN-Running/dp/B0FFLKC1J7" target="_blank" rel="nofollow" data-dimension112="a0202e0c-d1f4-11f1-b5ca-df3bb42b8d24" data-action="Deal Block" data-label="Superblast 2 (Unisex)" data-dimension48="Superblast 2 (Unisex)" data-dimension25="$149">View Deal</a></p></div><div class="product"><a data-dimension112="a0202d9e-d1f4-11f1-abe6-29e36dbd375e" data-action="Deal Block" data-label="Gel-Nimbus 28 Running Shoes (Women's)" data-dimension48="Gel-Nimbus 28 Running Shoes (Women's)" data-dimension25="$154" href="https://www.amazon.com/ASICS-Womens-Gel-Nimbus%C2%AE-Mineral-Medium/dp/B0FV6VM7KX" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1155px;"><p class="vanilla-image-block" style="padding-top:51.77%;"><img id="X9qqNMWyXyfKdx37i3V59b" name="Gel-Nimbus 28 Running Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/X9qqNMWyXyfKdx37i3V59b-1920-80.jpg" mos="" align="middle" fullscreen="" width="1155" height="598" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Nimbus%C2%AE-Mineral-Medium/dp/B0FV6VM7KX" target="_blank" rel="nofollow" data-dimension112="a0202d9e-d1f4-11f1-abe6-29e36dbd375e" data-action="Deal Block" data-label="Gel-Nimbus 28 Running Shoes (Women's)" data-dimension48="Gel-Nimbus 28 Running Shoes (Women's)" data-dimension25="$154">Gel-Nimbus 28 Running Shoes (Women's): was $169 now $154</a></strong><br />If you love the style of the Gel-Nimbus running shoes and want the latest in the line, the Gel-Nimbus 28 have a small but significant 9% discount. They deliver a lightweight upper with plush cushioning and PureGel tech to propel you forwards.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Gel-Nimbus%C2%AE-Mineral-Medium/dp/B0FV6VM7KX" target="_blank" rel="nofollow" data-dimension112="a0202d9e-d1f4-11f1-abe6-29e36dbd375e" data-action="Deal Block" data-label="Gel-Nimbus 28 Running Shoes (Women's)" data-dimension48="Gel-Nimbus 28 Running Shoes (Women's)" data-dimension25="$154">View Deal</a></p></div><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Running&amp;view_mode=savings_squad&amp;widget_title=Shop+More+Running+Deals+Handpicked+by+Our+Editors&amp;widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&amp;bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                if (externalUrl) {                   if (seenUrls.has(externalUrl)) return;                  seenUrls.add(externalUrl);                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || '',                   authorName: article.articleauthortext ? article.articleauthortext[0] : (article.articleauthor ? article.articleauthor[0] : ''),                   authorRole: article.articleauthorrole ? article.articleauthorrole[0] : '',                   authorImage: article.articleauthormedia ? article.articleauthormedia[0] : '',                   documentUrl: article.documenturl ? article.documenturl[0] : '',                   modifiedDate: article.contentmodifieddate || article.modifieddate || ''                });             });          });                    const airedaleBrandsList = Object.keys(overallBrandsCounts).map(b => ({              formatted_value: b,              count: overallBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/running/asics-running-shoes-are-up-to-56-percent-off-17-best-deals-to-set-prs-this-fall</link>
                                                                            <description>
                            <![CDATA[ Don't miss your chance to get 50% off or more on Asics running shoes! Some of the best pairs we've tested are dropping in price. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">NiVfeV4w2NAteCPmj6hAWW</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/X9uTEjvQTcK8rRPWsELtu3-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 27 Oct 2026 11:41:02 +0000</pubDate>                                                                                                                                <updated>Fri, 30 Oct 2026 10:00:58 +0000</updated>
                                                                                                                                            <category><![CDATA[Running]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                                                                <author><![CDATA[ millie.daviswilliams@futurenet.com (Millie Davis-Williams) ]]></author>                    <dc:creator><![CDATA[ Millie Davis-Williams ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/WU6pa7hKuxs5ScCoqcXYWA-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Millie is a Deals Editor at Tom&#039;s Guide specializing in tech deals content. Based in London, Millie has spent a lifetime stubbornly refusing to pay full price on any possible purchase. She has years of searching for the best discounts on the latest and greatest phones, TVs and gadgets under her belt, and knows how to sort the best deals from the rest. Helping readers save on the products they want is her mission, whether it’s an Apple Watch or a new tablet.&lt;/p&gt;&lt;p&gt;Since working at Tom’s Guide, Millie has covered retail events like Prime Day, Black Friday and Cyber Monday extensively, meaning she knows the products readers are looking for and the best times of year to hit “purchase.”&lt;/p&gt;&lt;p&gt;When she’s not looking for discounts, Millie covers news and writes how-to articles about everything from phones, streaming devices, and headphones to apps and video games.&lt;/p&gt;&lt;p&gt;In her spare time, Millie enjoys reading, gaming on her Nintendo Switch and creating digital art. She’s also a fan of watching Disney movies and collecting plush (the latter having totally taken over her bedroom.)&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/X9uTEjvQTcK8rRPWsELtu3-1920-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Asics Novablast 5 running shoes]]></media:description>                                                            <media:text><![CDATA[Asics Novablast 5 running shoes]]></media:text>
                                <media:title type="plain"><![CDATA[Asics Novablast 5 running shoes]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/X9uTEjvQTcK8rRPWsELtu3-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Asics running shoes are some of the most popular on the market — and some of the <a href="https://www.tomsguide.com/best-picks/best-running-shoes">best running shoes</a> we've tested, too. If you're hoping to improve your PRs this fall, make sure to check out these Asics running shoe deals at Amazon.</p><p>My favorite deal right now is the <a href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Cobalt/dp/B0F63X6TCG/" target="_blank" rel="nofollow">Asics Novablast 5 on sale from $129</a>. It's a previous winner on our list of the best running shoes, and it's still a great buy today because of its comfortable, smooth feel.</p><p><strong>Note: </strong>Prices can vary depending on the size and color you choose — check out any different color options in your size to find the best deals.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links </span></h3><ul><li><a href="https://www.amazon.com/stores/ASICS/page/3D51EC88-4320-4F70-8CAF-9E7C77D723E2" target="_blank" rel="nofollow"><strong>shop all Asics deals on Amazon</strong></a></li><li><strong>Asics Gel-Kayano 30 (Women's): </strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow"><strong>was $160 now from $69</strong></a></li><li><strong>Asics Versablast 4 Running Shoes (Women's): </strong><a href="https://www.amazon.com/ASICS-Womens-VERSABLAST-Running-Shoes/dp/B0F5CSWHS6" target="_blank" rel="nofollow"><strong>was $80 now from $69</strong></a></li><li><strong>Asics Novablast 5 (Men's): </strong><a href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow"><strong>was $160 now from $129</strong></a></li><li><strong>Asics Superblast 2 (Unisex): </strong><a href="https://www.amazon.com/ASICS-Unisex-SUPERBLAST-EKIDEN-Running/dp/B0FFKVZV1D" target="_blank" rel="nofollow"><strong>was $199 now $149</strong></a></li></ul><h3 class="article-body__section" id="section-asics-shoes"><span>Asics Shoes</span></h3><div class="product"><a data-dimension112="20582a14-d382-11f1-ae82-0397e4ad8870" data-action="Deal Block" data-label="Gel-Contend 9 (Men's)" data-dimension48="Gel-Contend 9 (Men's)" data-dimension25="$54" href="https://www.amazon.com/ASICS-Gel-Contend-Running-Shoes-Carrier/dp/B0F6NQLR41" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:44.38%;"><img id="aWiLt2wFJJJbFXnkXMA5bD" name="Gel-Contend 9 (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/aWiLt2wFJJJbFXnkXMA5bD-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="513" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Gel-Contend-Running-Shoes-Carrier/dp/B0F6NQLR41" target="_blank" rel="nofollow" data-dimension112="20582a14-d382-11f1-ae82-0397e4ad8870" data-action="Deal Block" data-label="Gel-Contend 9 (Men's)" data-dimension48="Gel-Contend 9 (Men's)" data-dimension25="$54">Gel-Contend 9 (Men's): was $75 now $54</a></strong><br />The ASICS GEL-Contend 9 is a great all around shoe with a breathable upper that moves with your foot and has extra cushioning to keep things soft underfoot. It’s ideal if you’re new to running or want a budget-friendly shoe that feels supportive for workouts, easy miles or long walks.<a class="view-deal button" href="https://www.amazon.com/ASICS-Gel-Contend-Running-Shoes-Carrier/dp/B0F6NQLR41" target="_blank" rel="nofollow" data-dimension112="20582a14-d382-11f1-ae82-0397e4ad8870" data-action="Deal Block" data-label="Gel-Contend 9 (Men's)" data-dimension48="Gel-Contend 9 (Men's)" data-dimension25="$54">View Deal</a></p></div><div class="product"><a data-dimension112="a02025e2-d1f4-11f1-a79a-cb46f224f8bf" data-action="Deal Block" data-label="Gel-Venture 9 Running Shoes (Men's)" data-dimension48="Gel-Venture 9 Running Shoes (Men's)" data-dimension25="$59" href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Sheet/dp/B0B47YVK12" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1157px;"><p class="vanilla-image-block" style="padding-top:45.55%;"><img id="FGGxuYvWwdm7YU6PMbr6B9" name="Gel-Venture 9 Running Shoes (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/FGGxuYvWwdm7YU6PMbr6B9-1920-80.jpg" mos="" align="middle" fullscreen="" width="1157" height="527" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Sheet/dp/B0B47YVK12" target="_blank" rel="nofollow" data-dimension112="a02025e2-d1f4-11f1-a79a-cb46f224f8bf" data-action="Deal Block" data-label="Gel-Venture 9 Running Shoes (Men's)" data-dimension48="Gel-Venture 9 Running Shoes (Men's)" data-dimension25="$59">Gel-Venture 9 Running Shoes (Men's): was $80 now $59</a></strong><br />Score the Asics Gel Venture 9 Running Shoes on sale from $59 at Amazon. These shoes are excellent for trail runs, with a traction pattern designed to support you on outdoor terrain. They also feature Rearfoot GEL to absorb impact and super-soft AMPLIFOAM cushioning.<a class="view-deal button" href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Sheet/dp/B0B47YVK12" target="_blank" rel="nofollow" data-dimension112="a02025e2-d1f4-11f1-a79a-cb46f224f8bf" data-action="Deal Block" data-label="Gel-Venture 9 Running Shoes (Men's)" data-dimension48="Gel-Venture 9 Running Shoes (Men's)" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="ce446306-d448-11f1-8ac3-1728603cf6ec" data-action="Deal Block" data-label="Game FlyteFoam Pickleball Shoes (Women's)" data-dimension48="Game FlyteFoam Pickleball Shoes (Women's)" data-dimension25="$59" href="https://www.amazon.com/ASICS-Womens-Pickleball-Tennis-Purple/dp/B0DP1D8RBK" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:47.49%;"><img id="PQguZuXt8VG966JUtq9TAS" name="Game FlyteFoam Pickleball Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/PQguZuXt8VG966JUtq9TAS-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="549" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Pickleball-Tennis-Purple/dp/B0DP1D8RBK" target="_blank" rel="nofollow" data-dimension112="ce446306-d448-11f1-8ac3-1728603cf6ec" data-action="Deal Block" data-label="Game FlyteFoam Pickleball Shoes (Women's)" data-dimension48="Game FlyteFoam Pickleball Shoes (Women's)" data-dimension25="$59">Game FlyteFoam Pickleball Shoes (Women's): was $90 now $59</a></strong><br />Improve your game with the Asics Game FlyteFoam Pickleball shoes! They're designed to have extra ventilation and flexibility to move with you and keep your feet from overheating.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Pickleball-Tennis-Purple/dp/B0DP1D8RBK" target="_blank" rel="nofollow" data-dimension112="ce446306-d448-11f1-8ac3-1728603cf6ec" data-action="Deal Block" data-label="Game FlyteFoam Pickleball Shoes (Women's)" data-dimension48="Game FlyteFoam Pickleball Shoes (Women's)" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="a02026b4-d1f4-11f1-bdf6-134aa1c2f7f4" data-action="Deal Block" data-label="Upcourt 6 Volleyball Shoes (Women's)" data-dimension48="Upcourt 6 Volleyball Shoes (Women's)" data-dimension25="$64" href="https://www.amazon.com/ASICS-Womens-Upcourt-Volleyball-Shoes/dp/B0GXCKGNNZ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1164px;"><p class="vanilla-image-block" style="padding-top:43.47%;"><img id="GzQK5bL8yXHCDELcBXQfqK" name="Upcourt 6 Volleyball Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/GzQK5bL8yXHCDELcBXQfqK-1920-80.jpg" mos="" align="middle" fullscreen="" width="1164" height="506" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Upcourt-Volleyball-Shoes/dp/B0GXCKGNNZ" target="_blank" rel="nofollow" data-dimension112="a02026b4-d1f4-11f1-bdf6-134aa1c2f7f4" data-action="Deal Block" data-label="Upcourt 6 Volleyball Shoes (Women's)" data-dimension48="Upcourt 6 Volleyball Shoes (Women's)" data-dimension25="$64">Upcourt 6 Volleyball Shoes (Women's): was $75 now $64</a></strong><br />Put your best foot forward on the volleyball court with the Asics Upcourt 6. These have a lightweight and flexible design, paired with soft and breathable mesh paneling across the upper. <a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Upcourt-Volleyball-Shoes/dp/B0GXCKGNNZ" target="_blank" rel="nofollow" data-dimension112="a02026b4-d1f4-11f1-bdf6-134aa1c2f7f4" data-action="Deal Block" data-label="Upcourt 6 Volleyball Shoes (Women's)" data-dimension48="Upcourt 6 Volleyball Shoes (Women's)" data-dimension25="$64">View Deal</a></p></div><div class="product"><a data-dimension112="a020279a-d1f4-11f1-947a-b3fde5bcce92" data-action="Deal Block" data-label="Women's Novablast 4" data-dimension48="Women's Novablast 4" data-dimension25="$67" href="https://www.amazon.com/ASICS-Womens-NOVABLAST-Running-Expanse/dp/B0CFP3J6RB" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1200px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="wMYSVC2325TPeXMt7TJ9t3" name="Asics Novablast 4" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/wMYSVC2325TPeXMt7TJ9t3-1920-80.jpg" mos="" align="middle" fullscreen="" width="1200" height="1200" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-NOVABLAST-Running-Expanse/dp/B0CFP3J6RB" target="_blank" rel="nofollow" data-dimension112="a020279a-d1f4-11f1-947a-b3fde5bcce92" data-action="Deal Block" data-label="Women's Novablast 4" data-dimension48="Women's Novablast 4" data-dimension25="$67">Women's Novablast 4: was $140 now $67</a></strong><br />Old but gold. While the Novablast 6 is now available, the Novablast 4 is beloved by the Tom's Guide team — especially our Fitness Editor Jane McGuire, who wrote: "I've run over 100 miles in this shoe, and it's still one I reach for when I'm heading out for a long run."<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-NOVABLAST-Running-Expanse/dp/B0CFP3J6RB" target="_blank" rel="nofollow" data-dimension112="a020279a-d1f4-11f1-947a-b3fde5bcce92" data-action="Deal Block" data-label="Women's Novablast 4" data-dimension48="Women's Novablast 4" data-dimension25="$67">View Deal</a></p></div><div class="product"><a data-dimension112="20582af0-d382-11f1-834e-cfb2699195da" data-action="Deal Block" data-label="Gel-Venture 10 (Women's)" data-dimension48="Gel-Venture 10 (Women's)" data-dimension25="$67" href="https://www.amazon.com/ASICS-Womens-Gel-Venture-Running-Gravel/dp/B0D461PLVS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:50.95%;"><img id="vp24xzcYprCWGX65bT4nnN" name="Gel-Venture 10 (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vp24xzcYprCWGX65bT4nnN-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="589" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Venture-Running-Gravel/dp/B0D461PLVS" target="_blank" rel="nofollow" data-dimension112="20582af0-d382-11f1-834e-cfb2699195da" data-action="Deal Block" data-label="Gel-Venture 10 (Women's)" data-dimension48="Gel-Venture 10 (Women's)" data-dimension25="$67">Gel-Venture 10 (Women's): was $80 now $67</a></strong><br />These shoes are excellent for runs, with a traction pattern designed to support you on outdoor terrain. They also feature Rearfoot GEL to absorb impact and super-soft AMPLIFOAM cushioning.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Gel-Venture-Running-Gravel/dp/B0D461PLVS" target="_blank" rel="nofollow" data-dimension112="20582af0-d382-11f1-834e-cfb2699195da" data-action="Deal Block" data-label="Gel-Venture 10 (Women's)" data-dimension48="Gel-Venture 10 (Women's)" data-dimension25="$67">View Deal</a></p></div><div class="product"><a data-dimension112="ce4463f6-d448-11f1-8a89-3b432f5e0f1b" data-action="Deal Block" data-label="Gel-Venture 11 Trail (Men's)" data-dimension48="Gel-Venture 11 Trail (Men's)" data-dimension25="$69" href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Steel/dp/B0FV7BC2RR" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1146px;"><p class="vanilla-image-block" style="padding-top:75.04%;"><img id="44i7uWA8WvTqRemkvKZpV6" name="Gel-Venture 11" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/44i7uWA8WvTqRemkvKZpV6-1920-80.jpg" mos="" align="middle" fullscreen="" width="1146" height="860" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Steel/dp/B0FV7BC2RR" target="_blank" rel="nofollow" data-dimension112="ce4463f6-d448-11f1-8a89-3b432f5e0f1b" data-action="Deal Block" data-label="Gel-Venture 11 Trail (Men's)" data-dimension48="Gel-Venture 11 Trail (Men's)" data-dimension25="$69">Gel-Venture 11 Trail (Men's): was $90 now $69</a></strong><br />The Asics Gel-Venture 11 are designed for everyday runs and hitting the trails! They have Amplifoam Plus midsole cushioning on board, and a 2mm higher stack height — 2mm of extra softness to absorb impact and keep you comfortable for hours.<a class="view-deal button" href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Steel/dp/B0FV7BC2RR" target="_blank" rel="nofollow" data-dimension112="ce4463f6-d448-11f1-8a89-3b432f5e0f1b" data-action="Deal Block" data-label="Gel-Venture 11 Trail (Men's)" data-dimension48="Gel-Venture 11 Trail (Men's)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="a0202876-d1f4-11f1-b807-b516cc2e03a1" data-action="Deal Block" data-label="Gel-Kayano 30 (Women's)" data-dimension48="Gel-Kayano 30 (Women's)" data-dimension25="$69" href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1160px;"><p class="vanilla-image-block" style="padding-top:46.29%;"><img id="iHsvdtLnzyeWEyCZV8HBYe" name="Gel-Kayano 30 (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/iHsvdtLnzyeWEyCZV8HBYe-1920-80.jpg" mos="" align="middle" fullscreen="" width="1160" height="537" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow" data-dimension112="a0202876-d1f4-11f1-b807-b516cc2e03a1" data-action="Deal Block" data-label="Gel-Kayano 30 (Women's)" data-dimension48="Gel-Kayano 30 (Women's)" data-dimension25="$69">Gel-Kayano 30 (Women's): was $160 now $69</a></strong><br />The Gel Kayano 30 running shoes are an older model, but they're amazingly cheap with 56% off. They're designed to provide advanced stability and soft cushioning for neutral runners and overpronators alike. Our Deals Editor-in-Chief, Louis Ramirez, wrote: "I've been using these shoes for almost two years now. (I loved them so much I bought a second pair months after buying my first pair). I find that they're great for casual runs on the treadmill, HIIT sessions, and long distance running outdoors."<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow" data-dimension112="a0202876-d1f4-11f1-b807-b516cc2e03a1" data-action="Deal Block" data-label="Gel-Kayano 30 (Women's)" data-dimension48="Gel-Kayano 30 (Women's)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="a0202952-d1f4-11f1-ac11-659affe7682f" data-action="Deal Block" data-label="Versablast 4 Running Shoes (Women's)" data-dimension48="Versablast 4 Running Shoes (Women's)" data-dimension25="$69" href="https://www.amazon.com/ASICS-Womens-VERSABLAST-Running-Shoes/dp/B0F5CSWHS6" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:46.97%;"><img id="aXzwegkSgySzw9j2Pjj42L" name="Versablast 4 Running Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/aXzwegkSgySzw9j2Pjj42L-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="543" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-VERSABLAST-Running-Shoes/dp/B0F5CSWHS6" target="_blank" rel="nofollow" data-dimension112="a0202952-d1f4-11f1-ac11-659affe7682f" data-action="Deal Block" data-label="Versablast 4 Running Shoes (Women's)" data-dimension48="Versablast 4 Running Shoes (Women's)" data-dimension25="$69">Versablast 4 Running Shoes (Women's): was $80 now $69</a></strong><br />Packed with Amplifoam+ cushioning, the Asics Versablast 4 are built to be both soft and responsive — and are now a steal with this discount. The Cream/Hazy Lilac colorway is gorgeous, too.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-VERSABLAST-Running-Shoes/dp/B0F5CSWHS6" target="_blank" rel="nofollow" data-dimension112="a0202952-d1f4-11f1-ac11-659affe7682f" data-action="Deal Block" data-label="Versablast 4 Running Shoes (Women's)" data-dimension48="Versablast 4 Running Shoes (Women's)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="a0202a10-d1f4-11f1-b27a-1f9e9608d731" data-action="Deal Block" data-label="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension48="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension25="$69" href="https://www.amazon.com/ASICS-Gel-Contend-Running-Shoes-Black/dp/B0GY9NML2X" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:45.42%;"><img id="yyx3Rc6DdUotj8NTEwFwLa" name="Gel-Contend 10 Road Running Shoes (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/yyx3Rc6DdUotj8NTEwFwLa-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="525" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Gel-Contend-Running-Shoes-Black/dp/B0GY9NML2X" target="_blank" rel="nofollow" data-dimension112="a0202a10-d1f4-11f1-b27a-1f9e9608d731" data-action="Deal Block" data-label="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension48="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension25="$69">Gel-Contend 10 Road Running Shoes (Men's): was $80 now $69</a></strong><br />The 10th iteration of Asics' budget-friendly road running shoes have dropped in price! They feature Amplifoam+ cushioning to support your runs and have a lightweight and breathable mesh upper.<a class="view-deal button" href="https://www.amazon.com/ASICS-Gel-Contend-Running-Shoes-Black/dp/B0GY9NML2X" target="_blank" rel="nofollow" data-dimension112="a0202a10-d1f4-11f1-b27a-1f9e9608d731" data-action="Deal Block" data-label="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension48="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="ce4464d2-d448-11f1-9719-8158578fad74" data-action="Deal Block" data-label="Gel-Pulse 16 (Women's)" data-dimension48="Gel-Pulse 16 (Women's)" data-dimension25="$73" href="https://www.amazon.com/ASICS-Womens-Gel-Pulse-Running-Midnight/dp/B0D462MWTB" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:48.88%;"><img id="Woj2dkTQp2a9nuWs5nFuDg" name="Gel-Pulse 16 (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Woj2dkTQp2a9nuWs5nFuDg-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="565" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Pulse-Running-Midnight/dp/B0D462MWTB" target="_blank" rel="nofollow" data-dimension112="ce4464d2-d448-11f1-9719-8158578fad74" data-action="Deal Block" data-label="Gel-Pulse 16 (Women's)" data-dimension48="Gel-Pulse 16 (Women's)" data-dimension25="$73">Gel-Pulse 16 (Women's): was $100 now $73</a></strong><br />This is one of the cheaper Asics running shoe deals you'll find, so this shoe is definitely worth a purchase. However, stock is limited, so act fast! It's regarded as a comfy and versatile sneaker that suits neutral runners in particular.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Gel-Pulse-Running-Midnight/dp/B0D462MWTB" target="_blank" rel="nofollow" data-dimension112="ce4464d2-d448-11f1-9719-8158578fad74" data-action="Deal Block" data-label="Gel-Pulse 16 (Women's)" data-dimension48="Gel-Pulse 16 (Women's)" data-dimension25="$73">View Deal</a></p></div><div class="product"><a data-dimension112="a0202a74-d1f4-11f1-b2f8-7183f742df15" data-action="Deal Block" data-label="Gel-Excite 11 (Women's)" data-dimension48="Gel-Excite 11 (Women's)" data-dimension25="$74" href="https://www.amazon.com/ASICS-Womens-Gel-Excite-Running-MORGANITE/dp/B0F64HHL33/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1163px;"><p class="vanilla-image-block" style="padding-top:58.73%;"><img id="ApA8TRKTowTCiYpEXd3LDK" name="gel excite" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ApA8TRKTowTCiYpEXd3LDK-1920-80.jpg" mos="" align="middle" fullscreen="" width="1163" height="683" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Excite-Running-MORGANITE/dp/B0F64HHL33/" target="_blank" rel="nofollow" data-dimension112="a0202a74-d1f4-11f1-b2f8-7183f742df15" data-action="Deal Block" data-label="Gel-Excite 11 (Women's)" data-dimension48="Gel-Excite 11 (Women's)" data-dimension25="$74">Gel-Excite 11 (Women's): was $90 now $74</a></strong><br />The Gel-Excite 11 are now on sale for a discount, bringing their price under $75. Designed for running and fitness, it brings a higher stack and a super soft and comfortable feel underfoot. The reflective details are also handy if you're working out in low light.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Gel-Excite-Running-MORGANITE/dp/B0F64HHL33/" target="_blank" rel="nofollow" data-dimension112="a0202a74-d1f4-11f1-b2f8-7183f742df15" data-action="Deal Block" data-label="Gel-Excite 11 (Women's)" data-dimension48="Gel-Excite 11 (Women's)" data-dimension25="$74">View Deal</a></p></div><div class="product"><a data-dimension112="a0202ad8-d1f4-11f1-8e40-9fd6e825c988" data-action="Deal Block" data-label="GT-1000 14 Running Shoes (Women's)" data-dimension48="GT-1000 14 Running Shoes (Women's)" data-dimension25="$79" href="https://www.amazon.com/ASICS-Womens-GT-1000-Running-Shoes/dp/B0F5YXB9D6/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:49.57%;"><img id="ep5SNjswGLfrwX5LzXTK85" name="GT-1000 14 Running Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ep5SNjswGLfrwX5LzXTK85-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="573" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-GT-1000-Running-Shoes/dp/B0F5YXB9D6/" target="_blank" rel="nofollow" data-dimension112="a0202ad8-d1f4-11f1-8e40-9fd6e825c988" data-action="Deal Block" data-label="GT-1000 14 Running Shoes (Women's)" data-dimension48="GT-1000 14 Running Shoes (Women's)" data-dimension25="$79">GT-1000 14 Running Shoes (Women's): was $110 now $79</a></strong><br />Asics' affordable series of GT-1000 running shoes are even better with a discount. The 14th iteration of the shoe features a 3D guidance system built in to keep you stable on your feet as you run! <a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-GT-1000-Running-Shoes/dp/B0F5YXB9D6/" target="_blank" rel="nofollow" data-dimension112="a0202ad8-d1f4-11f1-8e40-9fd6e825c988" data-action="Deal Block" data-label="GT-1000 14 Running Shoes (Women's)" data-dimension48="GT-1000 14 Running Shoes (Women's)" data-dimension25="$79">View Deal</a></p></div><div class="product"><a data-dimension112="a0202b3c-d1f4-11f1-a461-b7fff4f10045" data-action="Deal Block" data-label="Glideride Max (Men's)" data-dimension48="Glideride Max (Men's)" data-dimension25="$99" href="https://www.amazon.com/ASICS-GLIDERIDE-Running-Monument-Vanilla/dp/B0CT9HG8TB" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1157px;"><p class="vanilla-image-block" style="padding-top:50.91%;"><img id="ur2nzvnBf49fo9rfEakkpK" name="Glideride Max (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ur2nzvnBf49fo9rfEakkpK-1920-80.jpg" mos="" align="middle" fullscreen="" width="1157" height="589" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-GLIDERIDE-Running-Monument-Vanilla/dp/B0CT9HG8TB" target="_blank" rel="nofollow" data-dimension112="a0202b3c-d1f4-11f1-a461-b7fff4f10045" data-action="Deal Block" data-label="Glideride Max (Men's)" data-dimension48="Glideride Max (Men's)" data-dimension25="$99">Glideride Max (Men's): was $170 now $99</a></strong><br />At 42% off, the Asics Glideride are a steal. These come with GuideSole tech to help you save energy, keeping you going for longer. You also get FF Blast Max cushioning for a lightweight, soft feel.<a class="view-deal button" href="https://www.amazon.com/ASICS-GLIDERIDE-Running-Monument-Vanilla/dp/B0CT9HG8TB" target="_blank" rel="nofollow" data-dimension112="a0202b3c-d1f4-11f1-a461-b7fff4f10045" data-action="Deal Block" data-label="Glideride Max (Men's)" data-dimension48="Glideride Max (Men's)" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="a0202ba0-d1f4-11f1-94e7-f3067fc0bb7e" data-action="Deal Block" data-label="Gel-Cumulus 27 (Women's)" data-dimension48="Gel-Cumulus 27 (Women's)" data-dimension25="$89" href="https://www.amazon.com/ASICS-Womens-Gel-Cumulus-Running-Shoes/dp/B0D3XQD6XB" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1146px;"><p class="vanilla-image-block" style="padding-top:75.04%;"><img id="vX8LzAvqyUKUxX8CnAhi9b" name="Gel-Cumulus 27 Running Shoes (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vX8LzAvqyUKUxX8CnAhi9b-1920-80.webp" mos="" align="middle" fullscreen="" width="1146" height="860" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Cumulus-Running-Shoes/dp/B0D3XQD6XB" target="_blank" rel="nofollow" data-dimension112="a0202ba0-d1f4-11f1-94e7-f3067fc0bb7e" data-action="Deal Block" data-label="Gel-Cumulus 27 (Women's)" data-dimension48="Gel-Cumulus 27 (Women's)" data-dimension25="$89">Gel-Cumulus 27 (Women's): was $140 now $89</a></strong><br />The Asics Gel-Cumulus 27 often gets overlooked because of the popularity of the Novablast and Gel-Nimbus lines, but it's usually available for less than those shoes, and it's a comfortable, fairly lightweight daily trainer in its own right. We've tested the newer Gel-Cumulus 28 model, and it's not a major update on the 27, so this deal on the older shoe is much better value.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Gel-Cumulus-Running-Shoes/dp/B0D3XQD6XB" target="_blank" rel="nofollow" data-dimension112="a0202ba0-d1f4-11f1-94e7-f3067fc0bb7e" data-action="Deal Block" data-label="Gel-Cumulus 27 (Women's)" data-dimension48="Gel-Cumulus 27 (Women's)" data-dimension25="$89">View Deal</a></p></div><div class="product"><a data-dimension112="a0202bfa-d1f4-11f1-914a-99923e4e1c22" data-action="Deal Block" data-label="Sonicblast Road Running Shoes (Men's)" data-dimension48="Sonicblast Road Running Shoes (Men's)" data-dimension25="$105" href="https://www.amazon.com/Asics-SONICBLAST-Running-Winter-Stillwater/dp/B0DPLQ32YV" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1528px;"><p class="vanilla-image-block" style="padding-top:75.00%;"><img id="rD9sdYvxaqtEV2BgyMfTx" name="Sonicblast" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/rD9sdYvxaqtEV2BgyMfTx-1920-80.jpg" mos="" align="middle" fullscreen="" width="1528" height="1146" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Asics-SONICBLAST-Running-Winter-Stillwater/dp/B0DPLQ32YV" target="_blank" rel="nofollow" data-dimension112="a0202bfa-d1f4-11f1-914a-99923e4e1c22" data-action="Deal Block" data-label="Sonicblast Road Running Shoes (Men's)" data-dimension48="Sonicblast Road Running Shoes (Men's)" data-dimension25="$105">Sonicblast Road Running Shoes (Men's): was $180 now $105</a></strong><br />Suited for both fast runs and everyday training, the Asics Sonicblast are super lightweight and propulsive. There's an Astroplate mechanism to help you shoot forward, as well as FF Blast Max and FF Turbo cushioning for a bouncy feel underfoot.<a class="view-deal button" href="https://www.amazon.com/Asics-SONICBLAST-Running-Winter-Stillwater/dp/B0DPLQ32YV" target="_blank" rel="nofollow" data-dimension112="a0202bfa-d1f4-11f1-914a-99923e4e1c22" data-action="Deal Block" data-label="Sonicblast Road Running Shoes (Men's)" data-dimension48="Sonicblast Road Running Shoes (Men's)" data-dimension25="$105">View Deal</a></p></div><div class="product"><a data-dimension112="a0202c5e-d1f4-11f1-9225-994cdda92eb4" data-action="Deal Block" data-label="Gel-K1011 Sneakers (Men's)" data-dimension48="Gel-K1011 Sneakers (Men's)" data-dimension25="$99" href="https://www.amazon.com/ASICS-Unisex-GEL-K1011-Sportstyle-Shoes/dp/B0GZWDQHQH" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:48.88%;"><img id="BuedRkRo9MvaiVx2pUuCR6" name="Gel-K1011 Sneakers (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/BuedRkRo9MvaiVx2pUuCR6-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="565" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Unisex-GEL-K1011-Sportstyle-Shoes/dp/B0GZWDQHQH" target="_blank" rel="nofollow" data-dimension112="a0202c5e-d1f4-11f1-9225-994cdda92eb4" data-action="Deal Block" data-label="Gel-K1011 Sneakers (Men's)" data-dimension48="Gel-K1011 Sneakers (Men's)" data-dimension25="$99">Gel-K1011 Sneakers (Men's): was $140 now $99</a></strong><br />An iconic design and reliable comfort, what more could you want from a pair of sneakers? It takes cues from some of Asics' best shoes, with Gel-Kayano-inspired panels on the upper and the same midsole tooling system as the Gel-Cumulus 17.<a class="view-deal button" href="https://www.amazon.com/ASICS-Unisex-GEL-K1011-Sportstyle-Shoes/dp/B0GZWDQHQH" target="_blank" rel="nofollow" data-dimension112="a0202c5e-d1f4-11f1-9225-994cdda92eb4" data-action="Deal Block" data-label="Gel-K1011 Sneakers (Men's)" data-dimension48="Gel-K1011 Sneakers (Men's)" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="a0202cc2-d1f4-11f1-acaa-ad86d472601b" data-action="Deal Block" data-label="Fuji Lite 6 Trail Running Shoes (Men's)" data-dimension48="Fuji Lite 6 Trail Running Shoes (Men's)" data-dimension25="$99" href="https://www.amazon.com/ASICS-Trail-Running-Shoes-Aurora/dp/B0F643LGDW" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1146px;"><p class="vanilla-image-block" style="padding-top:75.04%;"><img id="QxFrVRALdPPJaEfNpoi4mP" name="Asics Fuji Lite 6" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/QxFrVRALdPPJaEfNpoi4mP-1920-80.png" mos="" align="middle" fullscreen="" width="1146" height="860" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Trail-Running-Shoes-Aurora/dp/B0F643LGDW" target="_blank" rel="nofollow" data-dimension112="a0202cc2-d1f4-11f1-acaa-ad86d472601b" data-action="Deal Block" data-label="Fuji Lite 6 Trail Running Shoes (Men's)" data-dimension48="Fuji Lite 6 Trail Running Shoes (Men's)" data-dimension25="$99">Fuji Lite 6 Trail Running Shoes (Men's): was $130 now $99</a></strong><br />The Fuji Lite 6 is a lightweight trail-running shoe that offers reliable grip and a speedy, responsive ride for your off-road runs. It's also <a href="https://www.asics.com/us/en-us/fuji-lite-6/p/ANA_1011C086-600.html" target="_blank" rel="nofollow">on sale at Asics</a>. For $99, it's a steal.<a class="view-deal button" href="https://www.amazon.com/ASICS-Trail-Running-Shoes-Aurora/dp/B0F643LGDW" target="_blank" rel="nofollow" data-dimension112="a0202cc2-d1f4-11f1-acaa-ad86d472601b" data-action="Deal Block" data-label="Fuji Lite 6 Trail Running Shoes (Men's)" data-dimension48="Fuji Lite 6 Trail Running Shoes (Men's)" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="a0202d26-d1f4-11f1-bc55-0b91dfbb0b83" data-action="Deal Block" data-label="Novablast 5 (Men's)" data-dimension48="Novablast 5 (Men's)" data-dimension25="$129" href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1166px;"><p class="vanilla-image-block" style="padding-top:48.80%;"><img id="4pk4xESon4iEcQDmd7TqZF" name="Novablast 5 (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4pk4xESon4iEcQDmd7TqZF-1920-80.jpg" mos="" align="middle" fullscreen="" width="1166" height="569" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow" data-dimension112="a0202d26-d1f4-11f1-bc55-0b91dfbb0b83" data-action="Deal Block" data-label="Novablast 5 (Men's)" data-dimension48="Novablast 5 (Men's)" data-dimension25="$129">Novablast 5 (Men's): was $160 now $129</a></strong><br />We voted the Asics Novablast 6 as the <a href="https://www.tomsguide.com/best-picks/best-running-shoes">best running shoes</a> you can buy right now, but before that, the <a href="https://www.tomsguide.com/wellness/running/asics-novablast-5-review">Asics Novablast 5</a> had the top spot. They quickly stood out for their balance of comfort, support and fun, making them a pair of shoes you will actually look forward to running in. They're lightweight, durable and have a soft, springy feel underfoot that helps absorb impact while keeping runs enjoyable.<a class="view-deal button" href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow" data-dimension112="a0202d26-d1f4-11f1-bc55-0b91dfbb0b83" data-action="Deal Block" data-label="Novablast 5 (Men's)" data-dimension48="Novablast 5 (Men's)" data-dimension25="$129">View Deal</a></p></div><div class="product"><a data-dimension112="a0202e0c-d1f4-11f1-b5ca-df3bb42b8d24" data-action="Deal Block" data-label="Superblast 2 (Unisex)" data-dimension48="Superblast 2 (Unisex)" data-dimension25="$149" href="https://www.amazon.com/ASICS-Unisex-SUPERBLAST-EKIDEN-Running/dp/B0FFLKC1J7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1146px;"><p class="vanilla-image-block" style="padding-top:75.04%;"><img id="6Ag4kfoS5FeA9rMnnhtmCF" name="Superblast 2 Ekiden (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/6Ag4kfoS5FeA9rMnnhtmCF-1920-80.webp" mos="" align="middle" fullscreen="" width="1146" height="860" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Unisex-SUPERBLAST-EKIDEN-Running/dp/B0FFLKC1J7" target="_blank" rel="nofollow" data-dimension112="a0202e0c-d1f4-11f1-b5ca-df3bb42b8d24" data-action="Deal Block" data-label="Superblast 2 (Unisex)" data-dimension48="Superblast 2 (Unisex)" data-dimension25="$149">Superblast 2 (Unisex): was $200 now $149</a></strong><br />In our <a href="https://www.tomsguide.com/wellness/running/i-ran-35-miles-in-the-asics-superblast-2-and-its-one-of-the-best-new-shoes-of-2024">Asics Superblast 2 review</a> we said they were one of the best shoes of the year they released. There are newer shoes on the market, but now, you can get them for 25% off. Our testers thought the Superblast 2 was amazing for long runs, and found it to be lightweight and versatile.<a class="view-deal button" href="https://www.amazon.com/ASICS-Unisex-SUPERBLAST-EKIDEN-Running/dp/B0FFLKC1J7" target="_blank" rel="nofollow" data-dimension112="a0202e0c-d1f4-11f1-b5ca-df3bb42b8d24" data-action="Deal Block" data-label="Superblast 2 (Unisex)" data-dimension48="Superblast 2 (Unisex)" data-dimension25="$149">View Deal</a></p></div><div class="product"><a data-dimension112="a0202d9e-d1f4-11f1-abe6-29e36dbd375e" data-action="Deal Block" data-label="Gel-Nimbus 28 Running Shoes (Women's)" data-dimension48="Gel-Nimbus 28 Running Shoes (Women's)" data-dimension25="$154" href="https://www.amazon.com/ASICS-Womens-Gel-Nimbus%C2%AE-Mineral-Medium/dp/B0FV6VM7KX" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1155px;"><p class="vanilla-image-block" style="padding-top:51.77%;"><img id="X9qqNMWyXyfKdx37i3V59b" name="Gel-Nimbus 28 Running Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/X9qqNMWyXyfKdx37i3V59b-1920-80.jpg" mos="" align="middle" fullscreen="" width="1155" height="598" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Nimbus%C2%AE-Mineral-Medium/dp/B0FV6VM7KX" target="_blank" rel="nofollow" data-dimension112="a0202d9e-d1f4-11f1-abe6-29e36dbd375e" data-action="Deal Block" data-label="Gel-Nimbus 28 Running Shoes (Women's)" data-dimension48="Gel-Nimbus 28 Running Shoes (Women's)" data-dimension25="$154">Gel-Nimbus 28 Running Shoes (Women's): was $169 now $154</a></strong><br />If you love the style of the Gel-Nimbus running shoes and want the latest in the line, the Gel-Nimbus 28 have a small but significant 9% discount. They deliver a lightweight upper with plush cushioning and PureGel tech to propel you forwards.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Gel-Nimbus%C2%AE-Mineral-Medium/dp/B0FV6VM7KX" target="_blank" rel="nofollow" data-dimension112="a0202d9e-d1f4-11f1-abe6-29e36dbd375e" data-action="Deal Block" data-label="Gel-Nimbus 28 Running Shoes (Women's)" data-dimension48="Gel-Nimbus 28 Running Shoes (Women's)" data-dimension25="$154">View Deal</a></p></div><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Running&amp;view_mode=savings_squad&amp;widget_title=Shop+More+Running+Deals+Handpicked+by+Our+Editors&amp;widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&amp;bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                if (externalUrl) {                   if (seenUrls.has(externalUrl)) return;                  seenUrls.add(externalUrl);                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || '',                   authorName: article.articleauthortext ? article.articleauthortext[0] : (article.articleauthor ? article.articleauthor[0] : ''),                   authorRole: article.articleauthorrole ? article.articleauthorrole[0] : '',                   authorImage: article.articleauthormedia ? article.articleauthormedia[0] : '',                   documentUrl: article.documenturl ? article.documenturl[0] : '',                   modifiedDate: article.contentmodifieddate || article.modifieddate || ''                });             });          });                    const airedaleBrandsList = Object.keys(overallBrandsCounts).map(b => ({              formatted_value: b,              count: overallBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I ran 40 miles in the Brooks Hyperion Max 4 — here’s why I think it misses the mark ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Brooks has thrown a lot at the Hyperion Max 4, and unfortunately it’s a shoe that ends up being less than the sum of its parts, partly because all those parts make it way too heavy to be an effective speed shoe.</p><p>I enjoyed some of my runs in the Hyperion Max 4, which has a bouncy midsole and does perform well as a long-run cruiser, but if you’re in the market for a fast training shoe, I could name many others that I’d buy ahead of it, and almost all of them would cost less too.</p><p>It’s also very similar to its predecessor, so even if you were keen to pick it up, you’d be better off finding the <a href="https://www.tomsguide.com/wellness/running/brooks-hyperion-max-3-review">Brooks Hyperion Max 3 </a>on sale.</p><p>The Brooks Hyperion Max 4 has some good ingredients, most notably the springy DNA Gold foam, but the line needs a rethink to compete with the <a href="https://www.tomsguide.com/best-picks/best-running-shoes">best running shoes</a> in its category, like the excellent<a href="https://www.tomsguide.com/wellness/running/weve-run-60-miles-in-the-new-balance-supercomp-rebel-v1-and-its-our-new-favorite-fast-training-shoe"> New Balance SC Rebel v1 </a>or <a href="https://www.tomsguide.com/wellness/running/hoka-mach-x3-review">Hoka Mach X3</a>.</p><h2 class="article-body__section" id="section-brooks-hyperion-max-4-review-price-and-availability"><span>Brooks Hyperion Max 4 review: price and availability</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="uSFaDuELpuL6BEtFJQc5YC" name="Brooks Hyperion Max 4" alt="Brooks Hyperion Max 4" src="https://cdn.mos.cms.futurecdn.net/uSFaDuELpuL6BEtFJQc5YC-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The Brooks Hyperion Max 4 launched in summer 2026 and costs $200 in the U.S. and £170 in the U.K., which is the same price as its predecessor.</p><p>It’s an expensive shoe, and while the price is around par for a plated super-trainer, the Hyperion Max 4 is undercut by some excellent fast training shoes like the <a href="https://www.tomsguide.com/wellness/running/its-been-over-a-year-since-i-reviewed-the-adidas-adizero-evo-sl-heres-5-reasons-why-its-still-my-go-to-running-shoe">Adidas Adizero Evo SL</a> and <a href="https://www.tomsguide.com/wellness/running/i-ran-50-miles-in-the-kiprun-kipstorm-tempo-and-its-a-fantastic-daily-trainer">Kiprun Kipstorm Tempo</a>.</p><h2 class="article-body__section" id="section-brooks-hyperion-max-4-review-design-and-fit"><span>Brooks Hyperion Max 4 review: design and fit</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="wA2vQiNFMa89f7BX3woi5D" name="Brooks Hyperion Max 4" alt="Brooks Hyperion Max 4" src="https://cdn.mos.cms.futurecdn.net/wA2vQiNFMa89f7BX3woi5D-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The Brooks Hyperion Max 4 is currently available in four colors, including the white and yellow design I tested, which fit me well in my normal running shoe size.</p><p>It’s a very high stack shoe, standing 45mm tall at the heel and 39mm at the forefoot for a 6mm drop.</p><p>At 10.8oz in my US men’s size 10, the Hyperion Max 4 is not just heavy for a speed shoe; it’s pretty heavy even compared to most of the cushioned shoes for easy training I tested these days. </p><h3 class="article-body__section" id="section-upper"><span>Upper</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="nbwPTGKdr9CaQiouZ95RSC" name="Brooks Hyperion Max 4" alt="Brooks Hyperion Max 4" src="https://cdn.mos.cms.futurecdn.net/nbwPTGKdr9CaQiouZ95RSC-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The Brooks Hyperion Max 4 has a mesh upper with padding around the collar of the shoe and a large, stiff internal heel counter at the back.</p><p>It’s not as thick and padded as the uppers on the brand’s cushioned shoes, like the <a href="https://www.tomsguide.com/wellness/running/brooks-glycerin-max-2-review">Brooks Glycerin Max 2</a>, but it’s still comfortable for long runs, though I think a thinner, more minimal upper would be good for cutting weight and making the shoe feel a bit quicker.</p><h3 class="article-body__section" id="section-midsole"><span>Midsole</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="wKeBAkQYULqWEPaGZQYABC" name="Brooks Hyperion Max 4" alt="Brooks Hyperion Max 4" src="https://cdn.mos.cms.futurecdn.net/wKeBAkQYULqWEPaGZQYABC-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Two foams are used in the midsole of the Hyperion Max 4, with the top layer being made from Brooks’ bouncy PEBA-based DNA Gold foam, and the bottom being a firmer supercritical EVA foam called DNA Flash v2.</p><p>In between these two foams runs a nylon plate that helps to stabilize the high stack and add some extra pop to your stride. The plate also creates a stiff feel to the ride, though it’s not as rigid as a carbon plate.</p><p>The Hyperion Max 4 has a rocker profile to help roll you from heel to toe smoothly with each step.</p><h3 class="article-body__section" id="section-outsole"><span>Outsole</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="u9xzMP9SobdhFLUS4CGsHC" name="Brooks Hyperion Max 4" alt="Brooks Hyperion Max 4" src="https://cdn.mos.cms.futurecdn.net/u9xzMP9SobdhFLUS4CGsHC-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>A thick layer of rubber is used at the heel and forefoot of the shoe and while this is good for durability, using a thinner material would help reduce the weight of the Hyperion Max 4 for fast running.</p><p>One way the shoe has shed some weight is a large cutout on the medial side of the shoe, but the placement of this cutout reduces the stability of the Hyperion Max 4 and might encourage pronation (inward rolling of the foot) when landing.</p><p>Midsole cutouts are common on fast shoes to reduce weight, but many brands opt to remove a central section of foam rather than at the sides to limit the instability created.</p><h2 class="article-body__section" id="section-brooks-hyperion-max-4-review-running-performance"><span>Brooks Hyperion Max 4 review: running performance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="jWcLJQBczbPVbjJLsthscC" name="Brooks Hyperion Max 4" alt="Brooks Hyperion Max 4" src="https://cdn.mos.cms.futurecdn.net/jWcLJQBczbPVbjJLsthscC-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>I used the Hyperion Max 4 for a variety of training runs, including some easy efforts, a progression run, and an 18-mile long run including 15 steady miles at sub-6/min per mile pace.</p><p>I’ve tested all four generations of the shoe to date, and it changed a lot in the first three, but the fourth feels similar to the Brooks Hyperion Max 3 to me.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="oWaYo8WsVkrHxYFHRzQ9vC" name="Brooks Hyperion Max 4" alt="Brooks Hyperion Max 4 and Brooks Hyperion Max 3" src="https://cdn.mos.cms.futurecdn.net/oWaYo8WsVkrHxYFHRzQ9vC-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>It’s big, it has some bounce and it rolls through smoothly, but the Hyperion Max 4 doesn’t feel great at faster paces. It’s too heavy and doesn’t have the nimble, aggressive feel of most speed shoes.</p><p>You can cruise along quite nicely in the shoe and it does have a comfortable and protective ride for long runs at a pace somewhere between easy and steady. However, at really easy paces, it feels a bit firm for me, and it isn’t especially stable because of the high stack and medial cutout.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="XaPfKMSfSu5cjXhB3EJgLC" name="Brooks Hyperion Max 4" alt="Brooks Hyperion Max 4" src="https://cdn.mos.cms.futurecdn.net/XaPfKMSfSu5cjXhB3EJgLC-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>In general, plated super-trainers like this are often among the most versatile shoes available in terms of the types of runs they work well for, but the Hyperion Max 4 doesn’t have that range — it’s cumbersome at fast paces and too stiff to truly enjoy on easy runs.</p><h2 class="article-body__section" id="section-should-you-buy-the-brooks-hyperion-max-4"><span>Should you buy the Brooks Hyperion Max 4?</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AYrQSpYwzwBpskM5rHeVjC" name="Brooks Hyperion Max 4" alt="Brooks Hyperion Max 4" src="https://cdn.mos.cms.futurecdn.net/AYrQSpYwzwBpskM5rHeVjC-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>I’d skip the Brooks Hyperion Max 4 if you’re in the market for a fast trainer right now, because there are many alternatives that offer a superior ride and/or better value.</p><p>The New Balance SC Rebel v1 is my favorite plated training shoe and while it’s also expensive, it delivers a truly fast and fun ride for workouts and can stand in for a full carbon super-shoe for races too.</p><p>More affordable speed shoes include the Adidas Evo SL, <a href="https://www.tomsguide.com/wellness/running/skechers-aero-razor-review">Skechers Aero Razor</a>, and Kiprun Kipstorm Tempo, which are much lighter than the Brooks and have more energetic rides for workouts.</p><p>If you’re looking for more of an all-rounder, then the <a href="https://www.tomsguide.com/wellness/running/ive-run-220-miles-in-the-asics-megablast-heres-5-reasons-why-its-my-go-to-shoe-for-marathon-training">Asics Megablast</a> is a little pricier than the Brooks, but much lighter and livelier on the run, and more enjoyable to use for easy or fast runs.</p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/running/i-ran-40-miles-in-the-brooks-hyperion-max-4-heres-why-i-think-it-misses-the-mark</link>
                                                                            <description>
                            <![CDATA[ The Brooks Hyperion Max 4 promises a speedy, springy ride for fast training, but it’s heavy and feels sluggish compared to the best rivals in its category. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">iCEaarFPjSM6Kw3zHmKiQ</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/ms3xHdXqo6TmCrPo3EZN3D-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 27 Oct 2026 10:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Running]]></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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/ms3xHdXqo6TmCrPo3EZN3D-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Brooks Hyperion Max 4 ]]></media:description>                                                            <media:text><![CDATA[Brooks Hyperion Max 4 ]]></media:text>
                                <media:title type="plain"><![CDATA[Brooks Hyperion Max 4 ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/ms3xHdXqo6TmCrPo3EZN3D-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Brooks has thrown a lot at the Hyperion Max 4, and unfortunately it’s a shoe that ends up being less than the sum of its parts, partly because all those parts make it way too heavy to be an effective speed shoe.</p><p>I enjoyed some of my runs in the Hyperion Max 4, which has a bouncy midsole and does perform well as a long-run cruiser, but if you’re in the market for a fast training shoe, I could name many others that I’d buy ahead of it, and almost all of them would cost less too.</p><p>It’s also very similar to its predecessor, so even if you were keen to pick it up, you’d be better off finding the <a href="https://www.tomsguide.com/wellness/running/brooks-hyperion-max-3-review">Brooks Hyperion Max 3 </a>on sale.</p><p>The Brooks Hyperion Max 4 has some good ingredients, most notably the springy DNA Gold foam, but the line needs a rethink to compete with the <a href="https://www.tomsguide.com/best-picks/best-running-shoes">best running shoes</a> in its category, like the excellent<a href="https://www.tomsguide.com/wellness/running/weve-run-60-miles-in-the-new-balance-supercomp-rebel-v1-and-its-our-new-favorite-fast-training-shoe"> New Balance SC Rebel v1 </a>or <a href="https://www.tomsguide.com/wellness/running/hoka-mach-x3-review">Hoka Mach X3</a>.</p><h2 class="article-body__section" id="section-brooks-hyperion-max-4-review-price-and-availability"><span>Brooks Hyperion Max 4 review: price and availability</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="uSFaDuELpuL6BEtFJQc5YC" name="Brooks Hyperion Max 4" alt="Brooks Hyperion Max 4" src="https://cdn.mos.cms.futurecdn.net/uSFaDuELpuL6BEtFJQc5YC-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The Brooks Hyperion Max 4 launched in summer 2026 and costs $200 in the U.S. and £170 in the U.K., which is the same price as its predecessor.</p><p>It’s an expensive shoe, and while the price is around par for a plated super-trainer, the Hyperion Max 4 is undercut by some excellent fast training shoes like the <a href="https://www.tomsguide.com/wellness/running/its-been-over-a-year-since-i-reviewed-the-adidas-adizero-evo-sl-heres-5-reasons-why-its-still-my-go-to-running-shoe">Adidas Adizero Evo SL</a> and <a href="https://www.tomsguide.com/wellness/running/i-ran-50-miles-in-the-kiprun-kipstorm-tempo-and-its-a-fantastic-daily-trainer">Kiprun Kipstorm Tempo</a>.</p><h2 class="article-body__section" id="section-brooks-hyperion-max-4-review-design-and-fit"><span>Brooks Hyperion Max 4 review: design and fit</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="wA2vQiNFMa89f7BX3woi5D" name="Brooks Hyperion Max 4" alt="Brooks Hyperion Max 4" src="https://cdn.mos.cms.futurecdn.net/wA2vQiNFMa89f7BX3woi5D-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The Brooks Hyperion Max 4 is currently available in four colors, including the white and yellow design I tested, which fit me well in my normal running shoe size.</p><p>It’s a very high stack shoe, standing 45mm tall at the heel and 39mm at the forefoot for a 6mm drop.</p><p>At 10.8oz in my US men’s size 10, the Hyperion Max 4 is not just heavy for a speed shoe; it’s pretty heavy even compared to most of the cushioned shoes for easy training I tested these days. </p><h3 class="article-body__section" id="section-upper"><span>Upper</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="nbwPTGKdr9CaQiouZ95RSC" name="Brooks Hyperion Max 4" alt="Brooks Hyperion Max 4" src="https://cdn.mos.cms.futurecdn.net/nbwPTGKdr9CaQiouZ95RSC-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The Brooks Hyperion Max 4 has a mesh upper with padding around the collar of the shoe and a large, stiff internal heel counter at the back.</p><p>It’s not as thick and padded as the uppers on the brand’s cushioned shoes, like the <a href="https://www.tomsguide.com/wellness/running/brooks-glycerin-max-2-review">Brooks Glycerin Max 2</a>, but it’s still comfortable for long runs, though I think a thinner, more minimal upper would be good for cutting weight and making the shoe feel a bit quicker.</p><h3 class="article-body__section" id="section-midsole"><span>Midsole</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="wKeBAkQYULqWEPaGZQYABC" name="Brooks Hyperion Max 4" alt="Brooks Hyperion Max 4" src="https://cdn.mos.cms.futurecdn.net/wKeBAkQYULqWEPaGZQYABC-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>Two foams are used in the midsole of the Hyperion Max 4, with the top layer being made from Brooks’ bouncy PEBA-based DNA Gold foam, and the bottom being a firmer supercritical EVA foam called DNA Flash v2.</p><p>In between these two foams runs a nylon plate that helps to stabilize the high stack and add some extra pop to your stride. The plate also creates a stiff feel to the ride, though it’s not as rigid as a carbon plate.</p><p>The Hyperion Max 4 has a rocker profile to help roll you from heel to toe smoothly with each step.</p><h3 class="article-body__section" id="section-outsole"><span>Outsole</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="u9xzMP9SobdhFLUS4CGsHC" name="Brooks Hyperion Max 4" alt="Brooks Hyperion Max 4" src="https://cdn.mos.cms.futurecdn.net/u9xzMP9SobdhFLUS4CGsHC-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>A thick layer of rubber is used at the heel and forefoot of the shoe and while this is good for durability, using a thinner material would help reduce the weight of the Hyperion Max 4 for fast running.</p><p>One way the shoe has shed some weight is a large cutout on the medial side of the shoe, but the placement of this cutout reduces the stability of the Hyperion Max 4 and might encourage pronation (inward rolling of the foot) when landing.</p><p>Midsole cutouts are common on fast shoes to reduce weight, but many brands opt to remove a central section of foam rather than at the sides to limit the instability created.</p><h2 class="article-body__section" id="section-brooks-hyperion-max-4-review-running-performance"><span>Brooks Hyperion Max 4 review: running performance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="jWcLJQBczbPVbjJLsthscC" name="Brooks Hyperion Max 4" alt="Brooks Hyperion Max 4" src="https://cdn.mos.cms.futurecdn.net/jWcLJQBczbPVbjJLsthscC-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>I used the Hyperion Max 4 for a variety of training runs, including some easy efforts, a progression run, and an 18-mile long run including 15 steady miles at sub-6/min per mile pace.</p><p>I’ve tested all four generations of the shoe to date, and it changed a lot in the first three, but the fourth feels similar to the Brooks Hyperion Max 3 to me.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="oWaYo8WsVkrHxYFHRzQ9vC" name="Brooks Hyperion Max 4" alt="Brooks Hyperion Max 4 and Brooks Hyperion Max 3" src="https://cdn.mos.cms.futurecdn.net/oWaYo8WsVkrHxYFHRzQ9vC-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>It’s big, it has some bounce and it rolls through smoothly, but the Hyperion Max 4 doesn’t feel great at faster paces. It’s too heavy and doesn’t have the nimble, aggressive feel of most speed shoes.</p><p>You can cruise along quite nicely in the shoe and it does have a comfortable and protective ride for long runs at a pace somewhere between easy and steady. However, at really easy paces, it feels a bit firm for me, and it isn’t especially stable because of the high stack and medial cutout.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="XaPfKMSfSu5cjXhB3EJgLC" name="Brooks Hyperion Max 4" alt="Brooks Hyperion Max 4" src="https://cdn.mos.cms.futurecdn.net/XaPfKMSfSu5cjXhB3EJgLC-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>In general, plated super-trainers like this are often among the most versatile shoes available in terms of the types of runs they work well for, but the Hyperion Max 4 doesn’t have that range — it’s cumbersome at fast paces and too stiff to truly enjoy on easy runs.</p><h2 class="article-body__section" id="section-should-you-buy-the-brooks-hyperion-max-4"><span>Should you buy the Brooks Hyperion Max 4?</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="AYrQSpYwzwBpskM5rHeVjC" name="Brooks Hyperion Max 4" alt="Brooks Hyperion Max 4" src="https://cdn.mos.cms.futurecdn.net/AYrQSpYwzwBpskM5rHeVjC-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>I’d skip the Brooks Hyperion Max 4 if you’re in the market for a fast trainer right now, because there are many alternatives that offer a superior ride and/or better value.</p><p>The New Balance SC Rebel v1 is my favorite plated training shoe and while it’s also expensive, it delivers a truly fast and fun ride for workouts and can stand in for a full carbon super-shoe for races too.</p><p>More affordable speed shoes include the Adidas Evo SL, <a href="https://www.tomsguide.com/wellness/running/skechers-aero-razor-review">Skechers Aero Razor</a>, and Kiprun Kipstorm Tempo, which are much lighter than the Brooks and have more energetic rides for workouts.</p><p>If you’re looking for more of an all-rounder, then the <a href="https://www.tomsguide.com/wellness/running/ive-run-220-miles-in-the-asics-megablast-heres-5-reasons-why-its-my-go-to-shoe-for-marathon-training">Asics Megablast</a> is a little pricier than the Brooks, but much lighter and livelier on the run, and more enjoyable to use for easy or fast runs.</p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ A master trainer gave me this low-impact core workout, and it’s a game-changer for strong abs and lower backs ]]></title>
                                                                                                <dc:content><![CDATA[ <p>While a sculpted midsection might be the goal for some, I want a strong core so I can do the activities I love longer without hurting my back. Since taking up Pilates, I've seen a huge difference in my core, so when LJ, a master trainer at London's <a href="https://www.1rebel.com/" target="_blank">1Rebel</a>, shared a five-move Pilates-inspired core workout with me, I couldn't wait to try it.</p><p>If you don't have access to a reformer bed, you can try using sliders instead, which are cheap and easy to buy from Amazon. If you want to stick to low-impact exercises, you're going to love the moves below. You don't need weights or any other equipment, and it's also accessible for most levels. </p><p>Here it is!</p><h2 id="watch-master-trainer-39-s-5-move-ab-workout">Watch: Master trainer's 5-move ab workout</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/De3x0AVzl0l/" target="_blank">A post shared by Tom's Guide Fitness | Workout Tips &amp; Gear (@tomsguidefitness)</a></p><p>A photo posted by </p></blockquote></div><p>LJ hasn't programmed sets, reps, or timing, but as a personal trainer myself, I would recommend programming 45 seconds on and 15 seconds off for 3-5 rounds. To make it more challenging, slow your tempo and program 50 seconds on instead.</p><p>My stomach has always been a problem area for me, but workouts like this have definitely made an enormous difference in developing strength, muscle and shape. I still maintain that your diet will move the needle most when it comes to how much muscle definition you show there, as well as other factors like health conditions, sleep, stress, lifting weights and genetics. </p><div class="product"><a data-dimension112="32dd6c9a-d12e-11f1-907c-3be3349cec07" data-action="Deal Block" data-label="Sliders" data-dimension48="Sliders" data-dimension25="$6" href="https://www.amazon.com/AZURELIFE-Exercise-Surfaces-Portable-Abdominal/dp/B07RK1CL2T" 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:71.47%;"><img id="kiNtDpQf9KK6Y9wRGLwAwg" name="sliders" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/kiNtDpQf9KK6Y9wRGLwAwg-1920-80.jpg" mos="" align="middle" fullscreen="" width="1500" height="1072" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>Azure life sliders are great for core workouts because they allow you to glide along the floor using your hands or feet if you can't access a reformer bed.<a class="view-deal button" href="https://www.amazon.com/AZURELIFE-Exercise-Surfaces-Portable-Abdominal/dp/B07RK1CL2T" target="_blank" rel="nofollow" data-dimension112="32dd6c9a-d12e-11f1-907c-3be3349cec07" data-action="Deal Block" data-label="Sliders" data-dimension48="Sliders" data-dimension25="$6">View Deal</a></p></div><ul><li><strong>Kneeling side kick (lateral core and glute stability): </strong>Start in a side-kneeling position, one hand down under your shoulder and the top leg extended straight out to the side. Keep your torso tall and still; kick the top leg forward, then sweep it back with control, without letting your hips or ribs collapse. <em><strong>Working: </strong></em>Obliques and deep lateral core for stability, plus gluteus medius and hip flexors on the working leg. </li><li><strong>Glute raise to heel slides outward: </strong>Lie on your back, knees bent, heels on sliders or the bed. Lift into a glute bridge, then slowly slide both heels outward to the sides, draw them back in, and lower with control. <em><strong>Working:</strong></em><em> </em>Glutes, hamstrings and adductors, with the core working to keep the pelvis level. The slide adds an eccentric challenge to the hamstrings and inner thighs.</li><li><strong>Wheelbarrow: </strong>Start in a strong plank with your hands on sliders or the bed. Brace your core, then push the sliders forward or your knees backward in a controlled line, keeping your hips level and ribs down. Drive back in to the start. <em><strong>Working: </strong></em>Deep core (transverse abdominis) and rectus abdominis, shoulders and lats for stability, and serratus anterior for scapular control. </li><li><strong>Glute bridge marches: </strong>Lie on your back with your knees bent, and lift into a glute bridge. Holding your hips high and level, alternate lifting one foot off the floor at a time as though marching on the spot. <em><strong>Working: </strong></em>Glutes and hamstrings holding the bridge, plus core and obliques resisting rotation and keeping the pelvis steady. This is great for single-leg stability.</li><li><strong>Criss-cross leg flutters: </strong>Lie on your back with your legs extended just off the floor and your lower back pressed into the mat. Flutter your legs up and down in small, quick movements,  crossing them over one another with each beat. <em><strong>Working:</strong></em><em> </em>Lower abdominals and hip flexors, plus inner thighs from the crossing action. It’s a good test of core control and endurance.</li></ul><h2 id="what-happened-when-i-tried-it-2">What happened when I tried it</h2><p>Try to keep the reps similar for each move in each round, and work both sides of the body. If you choose to do equal-number rounds, you could complete the reps on one side only, then switch to the other side on the next round.</p><div><blockquote><p>I kept my tempo slow and controlled, which delivered a strong burn in my core muscles and ensured I switched everything on to stay stable.</p></blockquote></div><p>This is a really great all-rounder, and you'll feel it everywhere. I kept my tempo slow and controlled, which delivered a strong burn in my core muscles and ensured I switched everything on to stay stable. </p><p>I used a reformer bed, but sliders work well, in my experience. I stuck to four rounds, which totaled a 20-minute workout, and my abs and shoulders were in pieces after. I had to keep remembering to use my breath, exhaling deeply during the phases of the exercises that created the most tension; this actually made me feel more in control and kept my body in a natural rhythm.</p><p>If you're new to core workouts or this type of routine, I strongly recommend taking it slowly and stopping if you experience any pain. </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><p>This isn't just about hitting your abs, though, although the rectus abdominis muscles along the front of your stomach are targeted. It's also about building deep core strength and working the muscles that protect your spine, like your hips, glutes and stabilizing layers of muscle.</p><p>If you suffer from tight hips or back pain, some (or all) of these moves might be useful for you to try, but <strong>stop and rest if you need to. </strong></p><p>If you're unsure <a href="https://www.tomsguide.com/news/this-is-the-most-important-thing-to-do-when-working-your-abs-according-to-a-personal-trainer">how to engage your core properly</a>, this <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">short "bracing" routine</a> might be helpful for you before you start the workout. </p><p>Also remember that training should make you feel good, so if ripped abs isn't the goal, that's great; focus on what you enjoy about the workout and let us know how you get on.</p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="vGnNDN" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-to-be-more-mobile-in-their-60s-and-70s-3-low-impact-exercises-you-should-start-with" target="_blank">I teach people to be more mobile in their 60s and 70s: 3 low-impact exercises you should start with</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/forget-burpees-the-pilates-burpee-is-beginner-friendly-and-low-impact-and-youll-love-it" target="_blank">Forget burpees —the 'Pilates burpee' is beginner-friendly and low-impact (and you’ll love it)</a></li><li><a href="https://www.tomsguide.com/wellness/workouts/a-yoga-instructor-says-this-is-the-5-minute-yoga-routine-you-need-for-strong-and-mobile-hips-and-core-muscles" target="_blank">A yoga instructor says this is the 5-minute yoga routine you need for strong and mobile hips and core muscles</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/workouts/a-master-trainer-gave-me-this-low-impact-core-workout-and-its-a-game-changer-for-strong-abs-and-lower-backs</link>
                                                                            <description>
                            <![CDATA[ 1Rebel master trainer LJ shares a short core workout to build strength — so we tried it. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">PeggF4bUj53aMPy4uWqu4B</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/M4nRXs7zE5LU76TAyhnNQP-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 27 Oct 2026 08: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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/M4nRXs7zE5LU76TAyhnNQP-1920-80.jpg">
                                                            <media:credit><![CDATA[Getty Images]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Image left, close up of woman with abs, image right, writer Sam taking a selfie in workout gear]]></media:description>                                                            <media:text><![CDATA[Image left, close up of woman with abs, image right, writer Sam taking a selfie in workout gear]]></media:text>
                                <media:title type="plain"><![CDATA[Image left, close up of woman with abs, image right, writer Sam taking a selfie in workout gear]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/M4nRXs7zE5LU76TAyhnNQP-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>While a sculpted midsection might be the goal for some, I want a strong core so I can do the activities I love longer without hurting my back. Since taking up Pilates, I've seen a huge difference in my core, so when LJ, a master trainer at London's <a href="https://www.1rebel.com/" target="_blank">1Rebel</a>, shared a five-move Pilates-inspired core workout with me, I couldn't wait to try it.</p><p>If you don't have access to a reformer bed, you can try using sliders instead, which are cheap and easy to buy from Amazon. If you want to stick to low-impact exercises, you're going to love the moves below. You don't need weights or any other equipment, and it's also accessible for most levels. </p><p>Here it is!</p><h2 id="watch-master-trainer-39-s-5-move-ab-workout">Watch: Master trainer's 5-move ab workout</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/De3x0AVzl0l/" target="_blank">A post shared by Tom's Guide Fitness | Workout Tips &amp; Gear (@tomsguidefitness)</a></p><p>A photo posted by </p></blockquote></div><p>LJ hasn't programmed sets, reps, or timing, but as a personal trainer myself, I would recommend programming 45 seconds on and 15 seconds off for 3-5 rounds. To make it more challenging, slow your tempo and program 50 seconds on instead.</p><p>My stomach has always been a problem area for me, but workouts like this have definitely made an enormous difference in developing strength, muscle and shape. I still maintain that your diet will move the needle most when it comes to how much muscle definition you show there, as well as other factors like health conditions, sleep, stress, lifting weights and genetics. </p><div class="product"><a data-dimension112="32dd6c9a-d12e-11f1-907c-3be3349cec07" data-action="Deal Block" data-label="Sliders" data-dimension48="Sliders" data-dimension25="$6" href="https://www.amazon.com/AZURELIFE-Exercise-Surfaces-Portable-Abdominal/dp/B07RK1CL2T" 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:71.47%;"><img id="kiNtDpQf9KK6Y9wRGLwAwg" name="sliders" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/kiNtDpQf9KK6Y9wRGLwAwg-1920-80.jpg" mos="" align="middle" fullscreen="" width="1500" height="1072" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>Azure life sliders are great for core workouts because they allow you to glide along the floor using your hands or feet if you can't access a reformer bed.<a class="view-deal button" href="https://www.amazon.com/AZURELIFE-Exercise-Surfaces-Portable-Abdominal/dp/B07RK1CL2T" target="_blank" rel="nofollow" data-dimension112="32dd6c9a-d12e-11f1-907c-3be3349cec07" data-action="Deal Block" data-label="Sliders" data-dimension48="Sliders" data-dimension25="$6">View Deal</a></p></div><ul><li><strong>Kneeling side kick (lateral core and glute stability): </strong>Start in a side-kneeling position, one hand down under your shoulder and the top leg extended straight out to the side. Keep your torso tall and still; kick the top leg forward, then sweep it back with control, without letting your hips or ribs collapse. <em><strong>Working: </strong></em>Obliques and deep lateral core for stability, plus gluteus medius and hip flexors on the working leg. </li><li><strong>Glute raise to heel slides outward: </strong>Lie on your back, knees bent, heels on sliders or the bed. Lift into a glute bridge, then slowly slide both heels outward to the sides, draw them back in, and lower with control. <em><strong>Working:</strong></em><em> </em>Glutes, hamstrings and adductors, with the core working to keep the pelvis level. The slide adds an eccentric challenge to the hamstrings and inner thighs.</li><li><strong>Wheelbarrow: </strong>Start in a strong plank with your hands on sliders or the bed. Brace your core, then push the sliders forward or your knees backward in a controlled line, keeping your hips level and ribs down. Drive back in to the start. <em><strong>Working: </strong></em>Deep core (transverse abdominis) and rectus abdominis, shoulders and lats for stability, and serratus anterior for scapular control. </li><li><strong>Glute bridge marches: </strong>Lie on your back with your knees bent, and lift into a glute bridge. Holding your hips high and level, alternate lifting one foot off the floor at a time as though marching on the spot. <em><strong>Working: </strong></em>Glutes and hamstrings holding the bridge, plus core and obliques resisting rotation and keeping the pelvis steady. This is great for single-leg stability.</li><li><strong>Criss-cross leg flutters: </strong>Lie on your back with your legs extended just off the floor and your lower back pressed into the mat. Flutter your legs up and down in small, quick movements,  crossing them over one another with each beat. <em><strong>Working:</strong></em><em> </em>Lower abdominals and hip flexors, plus inner thighs from the crossing action. It’s a good test of core control and endurance.</li></ul><h2 id="what-happened-when-i-tried-it-2">What happened when I tried it</h2><p>Try to keep the reps similar for each move in each round, and work both sides of the body. If you choose to do equal-number rounds, you could complete the reps on one side only, then switch to the other side on the next round.</p><div><blockquote><p>I kept my tempo slow and controlled, which delivered a strong burn in my core muscles and ensured I switched everything on to stay stable.</p></blockquote></div><p>This is a really great all-rounder, and you'll feel it everywhere. I kept my tempo slow and controlled, which delivered a strong burn in my core muscles and ensured I switched everything on to stay stable. </p><p>I used a reformer bed, but sliders work well, in my experience. I stuck to four rounds, which totaled a 20-minute workout, and my abs and shoulders were in pieces after. I had to keep remembering to use my breath, exhaling deeply during the phases of the exercises that created the most tension; this actually made me feel more in control and kept my body in a natural rhythm.</p><p>If you're new to core workouts or this type of routine, I strongly recommend taking it slowly and stopping if you experience any pain. </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><p>This isn't just about hitting your abs, though, although the rectus abdominis muscles along the front of your stomach are targeted. It's also about building deep core strength and working the muscles that protect your spine, like your hips, glutes and stabilizing layers of muscle.</p><p>If you suffer from tight hips or back pain, some (or all) of these moves might be useful for you to try, but <strong>stop and rest if you need to. </strong></p><p>If you're unsure <a href="https://www.tomsguide.com/news/this-is-the-most-important-thing-to-do-when-working-your-abs-according-to-a-personal-trainer">how to engage your core properly</a>, this <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">short "bracing" routine</a> might be helpful for you before you start the workout. </p><p>Also remember that training should make you feel good, so if ripped abs isn't the goal, that's great; focus on what you enjoy about the workout and let us know how you get on.</p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="vGnNDN" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-to-be-more-mobile-in-their-60s-and-70s-3-low-impact-exercises-you-should-start-with" target="_blank">I teach people to be more mobile in their 60s and 70s: 3 low-impact exercises you should start with</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/forget-burpees-the-pilates-burpee-is-beginner-friendly-and-low-impact-and-youll-love-it" target="_blank">Forget burpees —the 'Pilates burpee' is beginner-friendly and low-impact (and you’ll love it)</a></li><li><a href="https://www.tomsguide.com/wellness/workouts/a-yoga-instructor-says-this-is-the-5-minute-yoga-routine-you-need-for-strong-and-mobile-hips-and-core-muscles" target="_blank">A yoga instructor says this is the 5-minute yoga routine you need for strong and mobile hips and core muscles</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Struggle to squat? Here are five alternative moves for building stronger legs after 60 ]]></title>
                                                                                                <dc:content><![CDATA[ <p><a href="https://www.tomsguide.com/how-to/squats-how-to-do-them-and-the-benefits-for-building-leg-strength-and-muscle"><u>Squats</u></a> are one of the best-known exercises for building stronger legs, but that doesn’t mean they’re suitable for everyone. If you find squatting difficult because of stiff knees, limited mobility, or balance concerns, there are some great alternatives you can try — so you don’t have to miss out on building that all-important <a href="https://www.tomsguide.com/wellness/workouts/forget-squats-these-3-exercises-improve-single-leg-strength-stability-and-power"><u>lower-body strength</u></a>.</p><p>As we age, strong legs help us manage everyday activities like climbing stairs, getting up from a chair, and walking independently. And while squats are an <a href="https://www.tomsguide.com/wellness/workouts/squats-dont-just-build-strength-and-muscle-they-also-increase-functional-fitness-heres-3-of-my-favorites-to-try"><u>effective way to train several lower-body muscles at once</u></a>, they’re not the only option. Other exercises can also strengthen your thighs, hips and calves, without requiring you to lower your body into a deep squat.</p><p>Below, we’ve rounded up five alternative moves to help you build <a href="https://www.tomsguide.com/wellness/workouts/im-stronger-than-ever-at-70-here-are-6-exercises-to-build-strong-legs-according-to-a-70-year-old-fitness-coach"><u>stronger legs</u></a>. They can be adapted to different fitness levels, with options to use a sturdy chair or wall for extra support where needed. </p><p>The goal is to find exercises that feel comfortable for your body, while helping you maintain the strength and stability you rely on every day. Give the exercises below a try and you should start to notice a difference. </p><h3 class="article-body__section" id="section-1-seated-leg-extensions"><span>1. Seated leg extensions</span></h3><p>If bending your knees deeply feels uncomfortable, seated <a href="https://www.tomsguide.com/news/i-did-60-leg-extensions-every-day-for-a-week-heres-what-happened-to-my-legs"><u>leg extensions</u></a> are a useful alternative for strengthening your quadriceps — the muscles at the front of your thighs. These muscles help straighten your knees and play an important role in everyday activities like walking and climbing the stairs. Best of all, you can practice them without having to support your full body weight.</p><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/EAymwps5x0s" allowfullscreen=""></iframe></div></div><p><strong>How to do it:</strong></p><ul><li>Sit towards the front of a sturdy chair, with your back straight and both feet flat on the floor.</li><li>Slowly straighten one knee, lifting your foot until your leg is almost fully extended.</li><li>Pause for a second, keeping your thigh on the chair.</li><li>Lower your foot back to the floor with control.</li></ul><p><strong>Make it easier:</strong> Straighten your knee through a smaller range of motion, working only as far as feels comfortable.</p><p><strong>Make it harder:</strong> Hold your leg straight for three to five seconds before lowering it, or add a light ankle weight if you can do the movement comfortably and with control.</p><h3 class="article-body__section" id="section-2-standing-hamstring-curls"><span>2. Standing hamstring curls</span></h3><p>Your <a href="https://www.tomsguide.com/features/forget-squats-7-best-hamstring-exercises-to-build-stronger-legs-without-weights"><u>hamstrings</u></a> — the muscles at the backs of your thighs — help bend your knees and contribute to stability while walking. Standing <a href="https://www.tomsguide.com/how-to/how-to-do-hamstring-curl"><u>hamstring curls</u></a> strengthen these muscles without the effort of lowering your body into a squat. You can hold onto a sturdy chair or countertop if you struggle to <a href="https://www.tomsguide.com/wellness/workouts/can-you-stand-on-one-leg-for-30-seconds-heres-what-the-simple-balance-test-says-about-your-health"><u>balance on one leg</u></a>.</p><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/oWu8RxtWdGE" allowfullscreen=""></iframe></div></div><p><strong>How to do it</strong></p><ul><li>Stand tall behind a sturdy chair or countertop, holding on for support.</li><li>Keeping your thighs roughly in line with each other, bend one knee to bring your heel towards your buttocks.</li><li>Avoid leaning forward or arching your back as you lift your foot.</li><li>Slowly lower your foot back to the floor.</li></ul><p><strong>Make it easier:</strong> Bend your knee only a small amount, gradually increasing the range as your strength improves. Keep both hands on your support.</p><p><strong>Make it harder:</strong> Add a light ankle weight or resistance band, provided you can maintain good form and balance.</p><h3 class="article-body__section" id="section-3-standing-hip-extensions"><span>3. Standing hip extensions</span></h3><p>Our <a href="https://www.tomsguide.com/features/im-a-personal-trainer-here-are-5-glute-exercises-that-also-strengthen-your-back-without-weights"><u>glutes</u></a> are the primary engine for balance, posture, and independence as we age. Standing hip extensions target these muscles without the deep knee bend involved in squats, making them a useful alternative. </p><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/SWvnWGd0yQQ" allowfullscreen=""></iframe></div></div><p><strong>How to do it</strong></p><ul><li>Stand behind a sturdy chair or countertop for support.</li><li>Keep your back straight and your weight evenly distributed between your feet.</li><li>Slowly raise one leg backwards, keeping your knee mostly straight and your toes pointing forwards.</li><li>Stop before you feel the need to arch your lower back or lean forwards.</li><li>Bring your leg back to the starting position with control.</li></ul><p><strong>Make it easier:</strong> Move your leg backwards through a smaller range, keeping both hands on the support.</p><p><strong>Make it harder:</strong> Place a resistance band around your ankles, if you're comfortable using one.</p><h3 class="article-body__section" id="section-4-standing-side-leg-raises"><span>4. Standing side leg raises</span></h3><p>Standing side leg raises work the muscles around the outside of your hips, including the gluteus medius. These muscles help stabilize your pelvis when you stand on one leg during walking. It’s a particularly useful exercise for building <a href="https://www.tomsguide.com/wellness/workouts/i-test-hip-mobility-exercises-so-you-dont-have-to-this-one-move-always-stands-out"><u>hip strength</u></a> without requiring a deep bend in the knees.</p><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/l_U2uoePtS4" allowfullscreen=""></iframe></div></div><p><strong>How to do it</strong></p><ul><li>Stand tall beside a sturdy chair or countertop, holding on for support.</li><li>Keep your feet pointing forwards and your torso upright.</li><li>Slowly lift one leg out to the side, keeping your knee straight but not locked.</li><li>Avoid leaning your upper body in the opposite direction or turning your toes towards the ceiling.</li><li>Pause briefly, then lower your leg with control.</li></ul><p><strong>Make it easier:</strong> Lift your leg only a few inches, prioritising control over height. Use both hands on the support.</p><p><strong>Make it harder:</strong> Add a resistance band around your thighs, just above your knees.</p><h3 class="article-body__section" id="section-5-standing-calf-raises"><span>5. Standing calf raises</span></h3><p>Your calf muscles help propel you forwards as you walk and contribute to <a href="https://www.tomsguide.com/wellness/fitness/if-you-have-tight-ankles-or-stiff-joints-a-personal-trainer-recommends-these-3-underrated-mobility-exercises"><u>ankle stability</u></a>, so it’s important we keep them in check. <a href="https://www.tomsguide.com/wellness/workouts/im-a-personal-trainer-this-is-the-one-exercise-i-want-you-to-practice-daily-if-youre-over-60"><u>Calf raises</u></a> are a tried and tested exercise for strengthening the calves without bending your knees into a squat.</p><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/nnPGrBLNlaw" allowfullscreen=""></iframe></div></div><p><strong>How to do it</strong></p><ul><li>Stand behind a sturdy chair or countertop, with your feet hip-width apart.</li><li>Hold on for support and keep your torso upright.</li><li>Slowly lift your heels off the floor, rising onto the balls of your feet.</li><li>Pause at the top, then lower your heels slowly back to the floor.</li></ul><p><strong>Make it easier:</strong> Try <a href="https://www.tomsguide.com/features/i-did-100-seated-calf-raises-every-day-for-a-week-heres-what-happened"><u>seated calf raises</u></a> instead. Sit in a sturdy chair with your feet flat on the floor, then lift your heels while keeping the balls of your feet grounded.</p><p><strong>Make it harder:</strong> Try raising one heel at a time or slowing down the lowering phase to make your calves work harder.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.js" async=""></script><p>These exercises are proof that you don’t have to squat to build lower-body strength. Together, they target key lower-body muscles that support walking, balance and everyday movement as we age. </p><p>Start with one set of controlled repetitions for each exercise, and aim to practice them twice a week. Over time, your legs should start to feel stronger and more capable.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><strong></strong><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"><strong>I teach people how to be more mobile: 3 low-impact back and shoulder moves that build stability and strength after 40</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-how-to-be-strong-and-mobile-this-is-the-one-exercise-i-regret-ignoring-for-years" target="_blank"><strong>I teach people how to be strong and mobile: this is the one exercise I regret ignoring for years</strong></a><strong></strong></li><li><strong></strong><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"><strong>I teach people over 50 to be mobile: 3 low-impact moves that build more stability than a 30-minute walk</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/workouts/struggle-to-squat-here-are-five-alternative-moves-for-building-stronger-legs-after-60</link>
                                                                            <description>
                            <![CDATA[ 5 ways to build strong legs after 60, without doing a single squat ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">uh6zKSZKhkUEAPU3RCUNpF</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/r9EbytpDFfnu77oFtgdF9E-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 27 Oct 2026 07:00:00 +0000</pubDate>                                                                                                                                <updated>Tue, 27 Oct 2026 13:48:22 +0000</updated>
                                                                                                                                            <category><![CDATA[Workouts]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Katie Sims ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/9Ha2PHteeRRzUwJfKjgM7U-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/r9EbytpDFfnu77oFtgdF9E-1920-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-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p><a href="https://www.tomsguide.com/how-to/squats-how-to-do-them-and-the-benefits-for-building-leg-strength-and-muscle"><u>Squats</u></a> are one of the best-known exercises for building stronger legs, but that doesn’t mean they’re suitable for everyone. If you find squatting difficult because of stiff knees, limited mobility, or balance concerns, there are some great alternatives you can try — so you don’t have to miss out on building that all-important <a href="https://www.tomsguide.com/wellness/workouts/forget-squats-these-3-exercises-improve-single-leg-strength-stability-and-power"><u>lower-body strength</u></a>.</p><p>As we age, strong legs help us manage everyday activities like climbing stairs, getting up from a chair, and walking independently. And while squats are an <a href="https://www.tomsguide.com/wellness/workouts/squats-dont-just-build-strength-and-muscle-they-also-increase-functional-fitness-heres-3-of-my-favorites-to-try"><u>effective way to train several lower-body muscles at once</u></a>, they’re not the only option. Other exercises can also strengthen your thighs, hips and calves, without requiring you to lower your body into a deep squat.</p><p>Below, we’ve rounded up five alternative moves to help you build <a href="https://www.tomsguide.com/wellness/workouts/im-stronger-than-ever-at-70-here-are-6-exercises-to-build-strong-legs-according-to-a-70-year-old-fitness-coach"><u>stronger legs</u></a>. They can be adapted to different fitness levels, with options to use a sturdy chair or wall for extra support where needed. </p><p>The goal is to find exercises that feel comfortable for your body, while helping you maintain the strength and stability you rely on every day. Give the exercises below a try and you should start to notice a difference. </p><h3 class="article-body__section" id="section-1-seated-leg-extensions"><span>1. Seated leg extensions</span></h3><p>If bending your knees deeply feels uncomfortable, seated <a href="https://www.tomsguide.com/news/i-did-60-leg-extensions-every-day-for-a-week-heres-what-happened-to-my-legs"><u>leg extensions</u></a> are a useful alternative for strengthening your quadriceps — the muscles at the front of your thighs. These muscles help straighten your knees and play an important role in everyday activities like walking and climbing the stairs. Best of all, you can practice them without having to support your full body weight.</p><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/EAymwps5x0s" allowfullscreen=""></iframe></div></div><p><strong>How to do it:</strong></p><ul><li>Sit towards the front of a sturdy chair, with your back straight and both feet flat on the floor.</li><li>Slowly straighten one knee, lifting your foot until your leg is almost fully extended.</li><li>Pause for a second, keeping your thigh on the chair.</li><li>Lower your foot back to the floor with control.</li></ul><p><strong>Make it easier:</strong> Straighten your knee through a smaller range of motion, working only as far as feels comfortable.</p><p><strong>Make it harder:</strong> Hold your leg straight for three to five seconds before lowering it, or add a light ankle weight if you can do the movement comfortably and with control.</p><h3 class="article-body__section" id="section-2-standing-hamstring-curls"><span>2. Standing hamstring curls</span></h3><p>Your <a href="https://www.tomsguide.com/features/forget-squats-7-best-hamstring-exercises-to-build-stronger-legs-without-weights"><u>hamstrings</u></a> — the muscles at the backs of your thighs — help bend your knees and contribute to stability while walking. Standing <a href="https://www.tomsguide.com/how-to/how-to-do-hamstring-curl"><u>hamstring curls</u></a> strengthen these muscles without the effort of lowering your body into a squat. You can hold onto a sturdy chair or countertop if you struggle to <a href="https://www.tomsguide.com/wellness/workouts/can-you-stand-on-one-leg-for-30-seconds-heres-what-the-simple-balance-test-says-about-your-health"><u>balance on one leg</u></a>.</p><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/oWu8RxtWdGE" allowfullscreen=""></iframe></div></div><p><strong>How to do it</strong></p><ul><li>Stand tall behind a sturdy chair or countertop, holding on for support.</li><li>Keeping your thighs roughly in line with each other, bend one knee to bring your heel towards your buttocks.</li><li>Avoid leaning forward or arching your back as you lift your foot.</li><li>Slowly lower your foot back to the floor.</li></ul><p><strong>Make it easier:</strong> Bend your knee only a small amount, gradually increasing the range as your strength improves. Keep both hands on your support.</p><p><strong>Make it harder:</strong> Add a light ankle weight or resistance band, provided you can maintain good form and balance.</p><h3 class="article-body__section" id="section-3-standing-hip-extensions"><span>3. Standing hip extensions</span></h3><p>Our <a href="https://www.tomsguide.com/features/im-a-personal-trainer-here-are-5-glute-exercises-that-also-strengthen-your-back-without-weights"><u>glutes</u></a> are the primary engine for balance, posture, and independence as we age. Standing hip extensions target these muscles without the deep knee bend involved in squats, making them a useful alternative. </p><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/SWvnWGd0yQQ" allowfullscreen=""></iframe></div></div><p><strong>How to do it</strong></p><ul><li>Stand behind a sturdy chair or countertop for support.</li><li>Keep your back straight and your weight evenly distributed between your feet.</li><li>Slowly raise one leg backwards, keeping your knee mostly straight and your toes pointing forwards.</li><li>Stop before you feel the need to arch your lower back or lean forwards.</li><li>Bring your leg back to the starting position with control.</li></ul><p><strong>Make it easier:</strong> Move your leg backwards through a smaller range, keeping both hands on the support.</p><p><strong>Make it harder:</strong> Place a resistance band around your ankles, if you're comfortable using one.</p><h3 class="article-body__section" id="section-4-standing-side-leg-raises"><span>4. Standing side leg raises</span></h3><p>Standing side leg raises work the muscles around the outside of your hips, including the gluteus medius. These muscles help stabilize your pelvis when you stand on one leg during walking. It’s a particularly useful exercise for building <a href="https://www.tomsguide.com/wellness/workouts/i-test-hip-mobility-exercises-so-you-dont-have-to-this-one-move-always-stands-out"><u>hip strength</u></a> without requiring a deep bend in the knees.</p><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/l_U2uoePtS4" allowfullscreen=""></iframe></div></div><p><strong>How to do it</strong></p><ul><li>Stand tall beside a sturdy chair or countertop, holding on for support.</li><li>Keep your feet pointing forwards and your torso upright.</li><li>Slowly lift one leg out to the side, keeping your knee straight but not locked.</li><li>Avoid leaning your upper body in the opposite direction or turning your toes towards the ceiling.</li><li>Pause briefly, then lower your leg with control.</li></ul><p><strong>Make it easier:</strong> Lift your leg only a few inches, prioritising control over height. Use both hands on the support.</p><p><strong>Make it harder:</strong> Add a resistance band around your thighs, just above your knees.</p><h3 class="article-body__section" id="section-5-standing-calf-raises"><span>5. Standing calf raises</span></h3><p>Your calf muscles help propel you forwards as you walk and contribute to <a href="https://www.tomsguide.com/wellness/fitness/if-you-have-tight-ankles-or-stiff-joints-a-personal-trainer-recommends-these-3-underrated-mobility-exercises"><u>ankle stability</u></a>, so it’s important we keep them in check. <a href="https://www.tomsguide.com/wellness/workouts/im-a-personal-trainer-this-is-the-one-exercise-i-want-you-to-practice-daily-if-youre-over-60"><u>Calf raises</u></a> are a tried and tested exercise for strengthening the calves without bending your knees into a squat.</p><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/nnPGrBLNlaw" allowfullscreen=""></iframe></div></div><p><strong>How to do it</strong></p><ul><li>Stand behind a sturdy chair or countertop, with your feet hip-width apart.</li><li>Hold on for support and keep your torso upright.</li><li>Slowly lift your heels off the floor, rising onto the balls of your feet.</li><li>Pause at the top, then lower your heels slowly back to the floor.</li></ul><p><strong>Make it easier:</strong> Try <a href="https://www.tomsguide.com/features/i-did-100-seated-calf-raises-every-day-for-a-week-heres-what-happened"><u>seated calf raises</u></a> instead. Sit in a sturdy chair with your feet flat on the floor, then lift your heels while keeping the balls of your feet grounded.</p><p><strong>Make it harder:</strong> Try raising one heel at a time or slowing down the lowering phase to make your calves work harder.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.js" async=""></script><p>These exercises are proof that you don’t have to squat to build lower-body strength. Together, they target key lower-body muscles that support walking, balance and everyday movement as we age. </p><p>Start with one set of controlled repetitions for each exercise, and aim to practice them twice a week. Over time, your legs should start to feel stronger and more capable.</p><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><strong></strong><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"><strong>I teach people how to be more mobile: 3 low-impact back and shoulder moves that build stability and strength after 40</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-how-to-be-strong-and-mobile-this-is-the-one-exercise-i-regret-ignoring-for-years" target="_blank"><strong>I teach people how to be strong and mobile: this is the one exercise I regret ignoring for years</strong></a><strong></strong></li><li><strong></strong><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"><strong>I teach people over 50 to be mobile: 3 low-impact moves that build more stability than a 30-minute walk</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Alo Yoga's entire site is 30% off ahead of Black Friday — here are my 15 favorite deals ]]></title>
                                                                                                <dc:content><![CDATA[ <p>I'm a huge fan of Alo apparel. It's quickly become one of my go-to brands for working out, getting my steps in and even just lounging around the house. Their prices aren't considered cheap, but their clothes are comfortable, versatile and most importantly, they're durable. </p><p>Although the brand rarely has sales, Alo is currently hosting a <a href="https://www.aloyoga.com/?" target="_blank" rel="nofollow">huge Black Friday Early Access sale with 30% off sitewide</a>. In order to take advantage of this discount, you do have to sign up to become an Alo member, but it's free and extremely simple. (You can <a href="https://www.aloyoga.com/pages/access?" target="_blank" rel="nofollow">sign up at Alo Yoga</a>). Once you sign up, you can get 30% off literally anything you have your eyes set on.</p><p>Even better? Sale items are also slashing an extra 30% off — and my favorite deals start at just $31. We don't know how long this Early Access Sale will last, so we recommend shopping ASAP. Keep scrolling to check out my tried-and-true favorites from the sale.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><strong></strong><a href="https://www.aloyoga.com/collections/mens-sale?sort_by=PRICE_LOW_TO_HIGH" target="_blank" rel="nofollow"><strong>shop all men's Alo Yoga</strong></a><strong></strong></li><li><strong></strong><a href="https://www.aloyoga.com/collections/womens-sale-all?sort_by=PRICE_LOW_TO_HIGH" target="_blank" rel="nofollow"><strong>shop all women's Alo Yoga</strong></a><strong></strong></li><li><strong>Airlift Intrigue Bra: </strong><a href="https://www.aloyoga.com/products/w9557r-airlift-intrigue-bra-toasted-almond" target="_blank" rel="nofollow"><strong>was $78 now $31</strong></a></li><li><strong>Triumph Long Sleeve Tee: </strong><a href="https://www.aloyoga.com/products/m3079r-triumph-long-sleeve-tee-navy?" target="_blank" rel="nofollow"><strong>was $68 now $34</strong></a></li><li><strong>Airlift Redefine Bra: </strong><a href="https://www.aloyoga.com/products/w9796r-airlift-redefine-bra-black-white" target="_blank" rel="nofollow"><strong>was $88 now $44</strong></a><strong></strong></li><li><strong>Conquer Reform Mock Neck Long Sleeve: </strong><a href="https://www.aloyoga.com/products/m3218r-conquer-reform-mock-neck-long-sleeve-bone" target="_blank" rel="nofollow"><strong>was $98 now $49</strong></a><strong></strong></li><li><strong>Airlift Tennis Skirt: </strong><a href="https://www.aloyoga.com/products/w6435r-airlift-down-the-line-tennis-skirt-black" target="_blank" rel="nofollow"><strong>was $88 now $44</strong></a></li><li><strong>Alosoft Courtside Tennis Dress: </strong><a href="https://www.aloyoga.com/products/w8176r-alosoft-courtside-tennis-dress-white" target="_blank" rel="nofollow"><strong>was $118 now $47</strong></a></li><li><strong>Latitude 1/2 Zip Pullover: </strong><a href="https://www.aloyoga.com/products/m4161r-latitude-light-weight-1-2-zip-pullover-jacket-black" target="_blank" rel="nofollow"><strong>was $178 now $89</strong></a><strong></strong></li></ul><h3 class="article-body__section" id="section-best-alo-yoga-deals"><span>Best Alo Yoga Deals</span></h3><div class="product"><a data-dimension112="6a8e3f4c-d157-11f1-8710-b3c088979d80" data-action="Deal Block" data-label="Airlift Intrigue Bra (Women's)" data-dimension48="Airlift Intrigue Bra (Women's)" data-dimension25="$31" href="https://www.aloyoga.com/products/w9557r-airlift-intrigue-bra-toasted-almond" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:930px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="neAS4wnALZD9n5J3B3gd7T" name="Alo Yoga Airlift Intrigue Bra" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/neAS4wnALZD9n5J3B3gd7T-1920-80.jpg" mos="" align="middle" fullscreen="" width="930" height="1395" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/w9557r-airlift-intrigue-bra-toasted-almond" target="_blank" rel="nofollow" data-dimension112="6a8e3f4c-d157-11f1-8710-b3c088979d80" data-action="Deal Block" data-label="Airlift Intrigue Bra (Women's)" data-dimension48="Airlift Intrigue Bra (Women's)" data-dimension25="$31">Airlift Intrigue Bra (Women's): was $78 now $31</a></strong><br />The Airlift Intrigue Bra is made from Alo's signature Airlift fabric for a supportive and snug fit that's ready for everything from HIIT to headstands. (Alo recommends sizing up if you have a fuller cup size). The cut is simple but flattering, designed with a scoop-neck, adjustable straps that crisscross in back for extra lift. There's also a keyhole cutout.<a class="view-deal button" href="https://www.aloyoga.com/products/w9557r-airlift-intrigue-bra-toasted-almond" target="_blank" rel="nofollow" data-dimension112="6a8e3f4c-d157-11f1-8710-b3c088979d80" data-action="Deal Block" data-label="Airlift Intrigue Bra (Women's)" data-dimension48="Airlift Intrigue Bra (Women's)" data-dimension25="$31">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e3fc4-d157-11f1-8313-ad15c1a960be" data-action="Deal Block" data-label="Triumph Long Sleeve Tee (Men's)" data-dimension48="Triumph Long Sleeve Tee (Men's)" data-dimension25="$34" href="https://www.aloyoga.com/products/m3079r-triumph-long-sleeve-tee-navy?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="KRVhnW2jjpJGyTvpRk8pRD" name="long sleeve" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/KRVhnW2jjpJGyTvpRk8pRD-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/m3079r-triumph-long-sleeve-tee-navy?" target="_blank" rel="nofollow" data-dimension112="6a8e3fc4-d157-11f1-8313-ad15c1a960be" data-action="Deal Block" data-label="Triumph Long Sleeve Tee (Men's)" data-dimension48="Triumph Long Sleeve Tee (Men's)" data-dimension25="$34">Triumph Long Sleeve Tee (Men's): was $68 now $34</a></strong><br />You can never have enough tees — and this Alo long sleeve is airy, ultra-soft and perfect for training or layering under a light jacket. Plus, it's versatile enough that you can wear it just about anywhere. It's available in various colors.<a class="view-deal button" href="https://www.aloyoga.com/products/m3079r-triumph-long-sleeve-tee-navy?" target="_blank" rel="nofollow" data-dimension112="6a8e3fc4-d157-11f1-8313-ad15c1a960be" data-action="Deal Block" data-label="Triumph Long Sleeve Tee (Men's)" data-dimension48="Triumph Long Sleeve Tee (Men's)" data-dimension25="$34">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e403c-d157-11f1-b426-1dd511171f5a" data-action="Deal Block" data-label="Airlift Redefine Bra (Women's)" data-dimension48="Airlift Redefine Bra (Women's)" data-dimension25="$44" href="https://www.aloyoga.com/products/w9796r-airlift-redefine-bra-black-white" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:930px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="pW68i78BhEAGeRLXdzv3rB" name="Alo Yoga Airlift Redefine Bra" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pW68i78BhEAGeRLXdzv3rB-1920-80.jpg" mos="" align="middle" fullscreen="" width="930" height="1395" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/w9796r-airlift-redefine-bra-black-white" target="_blank" rel="nofollow" data-dimension112="6a8e403c-d157-11f1-b426-1dd511171f5a" data-action="Deal Block" data-label="Airlift Redefine Bra (Women's)" data-dimension48="Airlift Redefine Bra (Women's)" data-dimension25="$44">Airlift Redefine Bra (Women's): was $88 now $44</a></strong><br />The Airlift design features high-compression Airlift performance fabric, stitch lines, and corset detailing. It pairs well with the Infatuation leggings for a very cool finish. It's listed as medium support, which makes it a good option for everything from yoga to running.<a class="view-deal button" href="https://www.aloyoga.com/products/w9796r-airlift-redefine-bra-black-white" target="_blank" rel="nofollow" data-dimension112="6a8e403c-d157-11f1-b426-1dd511171f5a" data-action="Deal Block" data-label="Airlift Redefine Bra (Women's)" data-dimension48="Airlift Redefine Bra (Women's)" data-dimension25="$44">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e40b4-d157-11f1-aa15-5f5ef49a9db4" data-action="Deal Block" data-label="Airlift Down the Line Tennis Skirt (Women's)" data-dimension48="Airlift Down the Line Tennis Skirt (Women's)" data-dimension25="$44" href="https://www.aloyoga.com/products/w6435r-airlift-down-the-line-tennis-skirt-black" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:930px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="TZsSpJ3BxBmJ4ZL9FZvLXc" name="Alo Yoga Airlift Down The Line Tennis Skirt" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/TZsSpJ3BxBmJ4ZL9FZvLXc-1920-80.jpg" mos="" align="middle" fullscreen="" width="930" height="1395" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/w6435r-airlift-down-the-line-tennis-skirt-black" target="_blank" rel="nofollow" data-dimension112="6a8e40b4-d157-11f1-aa15-5f5ef49a9db4" data-action="Deal Block" data-label="Airlift Down the Line Tennis Skirt (Women's)" data-dimension48="Airlift Down the Line Tennis Skirt (Women's)" data-dimension25="$44">Airlift Down the Line Tennis Skirt (Women's): was $88 now $44</a></strong><br />This tennis skirt is made from Alo's signature Airlift fabric that provides a lightweight feel. It has detailed seams along the front for added definition along with a high-rise waist and built-in shorts (with a hidden pocket) that offers extra coverage on and off the court. <a class="view-deal button" href="https://www.aloyoga.com/products/w6435r-airlift-down-the-line-tennis-skirt-black" target="_blank" rel="nofollow" data-dimension112="6a8e40b4-d157-11f1-aa15-5f5ef49a9db4" data-action="Deal Block" data-label="Airlift Down the Line Tennis Skirt (Women's)" data-dimension48="Airlift Down the Line Tennis Skirt (Women's)" data-dimension25="$44">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e41a4-d157-11f1-9180-bbf59447b044" data-action="Deal Block" data-label="Alosoft Courtside Tennis Dress (Women's)" data-dimension48="Alosoft Courtside Tennis Dress (Women's)" data-dimension25="$47" href="https://www.aloyoga.com/products/w8176r-alosoft-courtside-tennis-dress-white" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="XKptohETcY85TbUyX5VLnX" name="alosoft" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XKptohETcY85TbUyX5VLnX-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/w8176r-alosoft-courtside-tennis-dress-white" target="_blank" rel="nofollow" data-dimension112="6a8e41a4-d157-11f1-9180-bbf59447b044" data-action="Deal Block" data-label="Alosoft Courtside Tennis Dress (Women's)" data-dimension48="Alosoft Courtside Tennis Dress (Women's)" data-dimension25="$47">Alosoft Courtside Tennis Dress (Women's): was $118 now $47</a></strong><br />This is more of a summer or warm-weather pick, but now that it's on sale, you might as well add it to your cart. This adorable tennis dress is made from Alo's signature Alosoft fabric and has a built-in onesie for all-in-one ease. It offers just the right amount of support, comfort and stretch and is perfect for any adventure.<a class="view-deal button" href="https://www.aloyoga.com/products/w8176r-alosoft-courtside-tennis-dress-white" target="_blank" rel="nofollow" data-dimension112="6a8e41a4-d157-11f1-9180-bbf59447b044" data-action="Deal Block" data-label="Alosoft Courtside Tennis Dress (Women's)" data-dimension48="Alosoft Courtside Tennis Dress (Women's)" data-dimension25="$47">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e412c-d157-11f1-9f4d-21cb954ebd0f" data-action="Deal Block" data-label="Conquer Reform Mock Neck Long Sleeve (Men's)" data-dimension48="Conquer Reform Mock Neck Long Sleeve (Men's)" data-dimension25="$49" href="https://www.aloyoga.com/products/m3218r-conquer-reform-mock-neck-long-sleeve-bone" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:930px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="mwpJoM9mJPUQGvQSzaW8P3" name="Alo Yoga Conquer Reform Mock Neck Long Sleeve" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/mwpJoM9mJPUQGvQSzaW8P3-1920-80.jpg" mos="" align="middle" fullscreen="" width="930" height="1395" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/m3218r-conquer-reform-mock-neck-long-sleeve-bone" target="_blank" rel="nofollow" data-dimension112="6a8e412c-d157-11f1-9f4d-21cb954ebd0f" data-action="Deal Block" data-label="Conquer Reform Mock Neck Long Sleeve (Men's)" data-dimension48="Conquer Reform Mock Neck Long Sleeve (Men's)" data-dimension25="$49">Conquer Reform Mock Neck Long Sleeve (Men's): was $98 now $49</a></strong><br />This Conquer Long Sleeve will leave you looking cool. It's made with Alo's signature stretchy, sweat-wicking Conquer fabric. It offers a slim fit, but it's not clingy. Plus, it'll feel ultra-soft against your skin with a cool buttery feel. <a class="view-deal button" href="https://www.aloyoga.com/products/m3218r-conquer-reform-mock-neck-long-sleeve-bone" target="_blank" rel="nofollow" data-dimension112="6a8e412c-d157-11f1-9f4d-21cb954ebd0f" data-action="Deal Block" data-label="Conquer Reform Mock Neck Long Sleeve (Men's)" data-dimension48="Conquer Reform Mock Neck Long Sleeve (Men's)" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e4212-d157-11f1-8057-03d73344435e" data-action="Deal Block" data-label="Conquer Reform Crewneck Short Sleeve (Men's)" data-dimension48="Conquer Reform Crewneck Short Sleeve (Men's)" data-dimension25="$54" href="https://www.aloyoga.com/products/m1205r-conquer-reform-crewneck-short-sleeve-black?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="SqWdyd5HuAWgavpBCsEErA" name="Alo t-shirt" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/SqWdyd5HuAWgavpBCsEErA-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/m1205r-conquer-reform-crewneck-short-sleeve-black?" target="_blank" rel="nofollow" data-dimension112="6a8e4212-d157-11f1-8057-03d73344435e" data-action="Deal Block" data-label="Conquer Reform Crewneck Short Sleeve (Men's)" data-dimension48="Conquer Reform Crewneck Short Sleeve (Men's)" data-dimension25="$54">Conquer Reform Crewneck Short Sleeve (Men's): was $78 now $54</a></strong><br />This Alo short sleeve is so versatile! It's airy, ultra-soft and perfect for training or layering under your favorite hoodie. I recommend grabbing one in several colors.<a class="view-deal button" href="https://www.aloyoga.com/products/m1205r-conquer-reform-crewneck-short-sleeve-black?" target="_blank" rel="nofollow" data-dimension112="6a8e4212-d157-11f1-8057-03d73344435e" data-action="Deal Block" data-label="Conquer Reform Crewneck Short Sleeve (Men's)" data-dimension48="Conquer Reform Crewneck Short Sleeve (Men's)" data-dimension25="$54">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e428a-d157-11f1-a682-3b05d21fb917" data-action="Deal Block" data-label="Accolade Short (Women's)" data-dimension48="Accolade Short (Women's)" data-dimension25="$54" href="https://www.aloyoga.com/products/w6472rg-accolade-short-athletic-heather-grey" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="VFMGYyj98EiJSVQw2DinSC" name="Alo Accolade shorts" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/VFMGYyj98EiJSVQw2DinSC-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/w6472rg-accolade-short-athletic-heather-grey" target="_blank" rel="nofollow" data-dimension112="6a8e428a-d157-11f1-a682-3b05d21fb917" data-action="Deal Block" data-label="Accolade Short (Women's)" data-dimension48="Accolade Short (Women's)" data-dimension25="$54">Accolade Short (Women's): was $78 now $54</a></strong><br />Elevate your loungewear collection with these super soft shorts that feature french terry fabric on the outside and warm fleece on the inside. I love wearing these cozy shorts around the house or when I'm walking my dog around the block during warmer weather. You'll definitely want to pair them with the stylish Accolade 1/4 Zip that I highlight further below. <a class="view-deal button" href="https://www.aloyoga.com/products/w6472rg-accolade-short-athletic-heather-grey" target="_blank" rel="nofollow" data-dimension112="6a8e428a-d157-11f1-a682-3b05d21fb917" data-action="Deal Block" data-label="Accolade Short (Women's)" data-dimension48="Accolade Short (Women's)" data-dimension25="$54">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e4302-d157-11f1-bef9-0f64c9ef4253" data-action="Deal Block" data-label="Airbrush Real Bra Tank (Women's)" data-dimension48="Airbrush Real Bra Tank (Women's)" data-dimension25="$54" href="https://www.aloyoga.com/products/w9587r-real-bra-tank-navy" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="YZ5EMQJNACcVfTogAGPsbU" name="Alo tank" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/YZ5EMQJNACcVfTogAGPsbU-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/w9587r-real-bra-tank-navy" target="_blank" rel="nofollow" data-dimension112="6a8e4302-d157-11f1-bef9-0f64c9ef4253" data-action="Deal Block" data-label="Airbrush Real Bra Tank (Women's)" data-dimension48="Airbrush Real Bra Tank (Women's)" data-dimension25="$54">Airbrush Real Bra Tank (Women's): was $78 now $54</a></strong><br />I can't get enough of this tank. So many fitness tanks are itchy and uncomfortable around the rib cage, but this one really does feel airbrushed with softness. I love its wide straps, flattering V-neckline and the fact that it has a built-in bra. Grab the matching yoga pants below to create your fabulous set.<a class="view-deal button" href="https://www.aloyoga.com/products/w9587r-real-bra-tank-navy" target="_blank" rel="nofollow" data-dimension112="6a8e4302-d157-11f1-bef9-0f64c9ef4253" data-action="Deal Block" data-label="Airbrush Real Bra Tank (Women's)" data-dimension48="Airbrush Real Bra Tank (Women's)" data-dimension25="$54">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e4370-d157-11f1-8070-ef5f7931ab86" data-action="Deal Block" data-label="5" Traction Shorts (Men's)" data-dimension48="5" Traction Shorts (Men's)" data-dimension25="$61" href="https://www.aloyoga.com/products/m6169r-5-traction-running-short-black" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="E2Ls8epEvgMgAdu9eiLz5G" name="Alo Yoga Traction Short" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/E2Ls8epEvgMgAdu9eiLz5G-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/m6169r-5-traction-running-short-black" target="_blank" rel="nofollow" data-dimension112="6a8e4370-d157-11f1-8070-ef5f7931ab86" data-action="Deal Block" data-label="5" Traction Shorts (Men's)" data-dimension48="5" Traction Shorts (Men's)" data-dimension25="$61">5" Traction Shorts (Men's): was $88 now $61</a></strong><br />Our Deals Editor in Chief can't recommend these shorts enough. First, they're very comfy with an elastic (but secure) waistband that stays in place even during the most intense HIIT sessions. The shorts are made of a slightly perforated, fast-drying fabric, which means they won't get heavy and weigh you down on those sweaty, humid runs. (Don't worry, they're not revealing). Are there cheaper options, yes, but these are a top choice.<a class="view-deal button" href="https://www.aloyoga.com/products/m6169r-5-traction-running-short-black" target="_blank" rel="nofollow" data-dimension112="6a8e4370-d157-11f1-8070-ef5f7931ab86" data-action="Deal Block" data-label="5" Traction Shorts (Men's)" data-dimension48="5" Traction Shorts (Men's)" data-dimension25="$61">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e43e8-d157-11f1-9cb8-4f1f4ca6232e" data-action="Deal Block" data-label="Airbrush High-Waist Highlight Goddess Legging (Women's)" data-dimension48="Airbrush High-Waist Highlight Goddess Legging (Women's)" data-dimension25="$64" href="https://www.aloyoga.com/products/w51207r-airbrush-high-waist-highlight-goddess-legging-black" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="873yoM5e6uuYF2aJS3ryiY" name="Alo deal" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/873yoM5e6uuYF2aJS3ryiY-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/w51207r-airbrush-high-waist-highlight-goddess-legging-black" target="_blank" rel="nofollow" data-dimension112="6a8e43e8-d157-11f1-9cb8-4f1f4ca6232e" data-action="Deal Block" data-label="Airbrush High-Waist Highlight Goddess Legging (Women's)" data-dimension48="Airbrush High-Waist Highlight Goddess Legging (Women's)" data-dimension25="$64">Airbrush High-Waist Highlight Goddess Legging (Women's): was $128 now $64</a></strong><br />These buttery-soft Alo leggings are supportive in all the right places, and right now, you can score 30% off in this black color. This is a total win for just under $100.<a class="view-deal button" href="https://www.aloyoga.com/products/w51207r-airbrush-high-waist-highlight-goddess-legging-black" target="_blank" rel="nofollow" data-dimension112="6a8e43e8-d157-11f1-9cb8-4f1f4ca6232e" data-action="Deal Block" data-label="Airbrush High-Waist Highlight Goddess Legging (Women's)" data-dimension48="Airbrush High-Waist Highlight Goddess Legging (Women's)" data-dimension25="$64">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e4460-d157-11f1-ba73-3b5eca588706" data-action="Deal Block" data-label="Latitude Light Weight 1/2 Zip Pullover Jacket (Men's)" data-dimension48="Latitude Light Weight 1/2 Zip Pullover Jacket (Men's)" data-dimension25="$89" href="https://www.aloyoga.com/products/m4161r-latitude-light-weight-1-2-zip-pullover-jacket-black" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:930px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="jpqrb3ejVXYMJ5LpcbTSNE" name="Alo Yoga Latitude Light Weight 1:2 Zip Pullover Jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jpqrb3ejVXYMJ5LpcbTSNE-1920-80.jpg" mos="" align="middle" fullscreen="" width="930" height="1395" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/m4161r-latitude-light-weight-1-2-zip-pullover-jacket-black" target="_blank" rel="nofollow" data-dimension112="6a8e4460-d157-11f1-ba73-3b5eca588706" data-action="Deal Block" data-label="Latitude Light Weight 1/2 Zip Pullover Jacket (Men's)" data-dimension48="Latitude Light Weight 1/2 Zip Pullover Jacket (Men's)" data-dimension25="$89">Latitude Light Weight 1/2 Zip Pullover Jacket (Men's): was $178 now $89</a></strong><br />Need a new fall jacket? This lightweight pullover is lightly filled (for a little warmth) and made from 100 percent nylon — the kind that's durable, swishy and ready to face the elements. It also has a half-zip collar, zippered side pockets, banded cuffs, and a banded hem. The fit is relaxed and comfortable.<a class="view-deal button" href="https://www.aloyoga.com/products/m4161r-latitude-light-weight-1-2-zip-pullover-jacket-black" target="_blank" rel="nofollow" data-dimension112="6a8e4460-d157-11f1-ba73-3b5eca588706" data-action="Deal Block" data-label="Latitude Light Weight 1/2 Zip Pullover Jacket (Men's)" data-dimension48="Latitude Light Weight 1/2 Zip Pullover Jacket (Men's)" data-dimension25="$89">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e45fa-d157-11f1-8d7e-8149ba49ea14" data-action="Deal Block" data-label="Airbrush High-Waist Bootcut Legging (Women's)" data-dimension48="Airbrush High-Waist Bootcut Legging (Women's)" data-dimension25="$89" href="https://www.aloyoga.com/products/w51118r-airbrush-high-waist-bootcut-legging-navy?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="Qsw5mp42qkqdNqEk5q5dBf" name="Alo yoga pant" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Qsw5mp42qkqdNqEk5q5dBf-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/w51118r-airbrush-high-waist-bootcut-legging-navy?" target="_blank" rel="nofollow" data-dimension112="6a8e45fa-d157-11f1-8d7e-8149ba49ea14" data-action="Deal Block" data-label="Airbrush High-Waist Bootcut Legging (Women's)" data-dimension48="Airbrush High-Waist Bootcut Legging (Women's)" data-dimension25="$89">Airbrush High-Waist Bootcut Legging (Women's): was $128 now $89</a></strong><br />I'm actually wearing these bootcut leggings as I write this! They are my all-time favorite legging, not only because they're comfortable, but because they're extremely flattering. I wear them literally everywhere and usually pair them with sneakers. They look great whether you're working out, walking or just want to put together a cute and casual weekend outfit. I definitely recommend these versatile leggings. <a class="view-deal button" href="https://www.aloyoga.com/products/w51118r-airbrush-high-waist-bootcut-legging-navy?" target="_blank" rel="nofollow" data-dimension112="6a8e45fa-d157-11f1-8d7e-8149ba49ea14" data-action="Deal Block" data-label="Airbrush High-Waist Bootcut Legging (Women's)" data-dimension48="Airbrush High-Waist Bootcut Legging (Women's)" data-dimension25="$89">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e467c-d157-11f1-aa03-b981bfb8fb48" data-action="Deal Block" data-label="7/8 High-Waist Airlift Legging (Women's)" data-dimension48="7/8 High-Waist Airlift Legging (Women's)" data-dimension25="$93" href="https://www.aloyoga.com/products/w5766r-7-8-high-waist-airlift-legging-black?variant=38169647710388" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="ZEAYKdVRTdVimtce8fAB2P" name="Alo leggings" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZEAYKdVRTdVimtce8fAB2P-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/w5766r-7-8-high-waist-airlift-legging-black?variant=38169647710388" target="_blank" rel="nofollow" data-dimension112="6a8e467c-d157-11f1-aa03-b981bfb8fb48" data-action="Deal Block" data-label="7/8 High-Waist Airlift Legging (Women's)" data-dimension48="7/8 High-Waist Airlift Legging (Women's)" data-dimension25="$93">7/8 High-Waist Airlift Legging (Women's): was $134 now $93</a></strong><br />These buttery-soft Alo leggings are supportive in all the right places, and right now, you can score 30% off in a rainbow of colors. This is a total win for just under $100. <a class="view-deal button" href="https://www.aloyoga.com/products/w5766r-7-8-high-waist-airlift-legging-black?variant=38169647710388" target="_blank" rel="nofollow" data-dimension112="6a8e467c-d157-11f1-aa03-b981bfb8fb48" data-action="Deal Block" data-label="7/8 High-Waist Airlift Legging (Women's)" data-dimension48="7/8 High-Waist Airlift Legging (Women's)" data-dimension25="$93">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e46f4-d157-11f1-96bd-4771f143ee8a" data-action="Deal Block" data-label="Accolade 1/4 Zip Pullover (Women's)" data-dimension48="Accolade 1/4 Zip Pullover (Women's)" data-dimension25="$103" href="https://www.aloyoga.com/products/u3040rg-accolade-1-4-zip-pullover-athletic-heather-grey?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="7ffv5DbfcMMrS4QEmnYHug" name="Accolade sweathshirt" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/7ffv5DbfcMMrS4QEmnYHug-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/u3040rg-accolade-1-4-zip-pullover-athletic-heather-grey?" target="_blank" rel="nofollow" data-dimension112="6a8e46f4-d157-11f1-96bd-4771f143ee8a" data-action="Deal Block" data-label="Accolade 1/4 Zip Pullover (Women's)" data-dimension48="Accolade 1/4 Zip Pullover (Women's)" data-dimension25="$103">Accolade 1/4 Zip Pullover (Women's): was $148 now $103</a></strong><br />If you're anything like me, you'll be living in this cozy 1/4 zip. It's an absolute must for crisp spring mornings thanks to its fleece interior. It comes in a variety of colors and matches perfectly with the Accolade shorts above. It also has a <a href="https://www.aloyoga.com/products/u5012rg-accolade-straight-leg-swtpnt-athletic-heather-grey" target="_blank" rel="nofollow">matching pair of sweatpants</a> if you want to be extra warm and cozy.<a class="view-deal button" href="https://www.aloyoga.com/products/u3040rg-accolade-1-4-zip-pullover-athletic-heather-grey?" target="_blank" rel="nofollow" data-dimension112="6a8e46f4-d157-11f1-96bd-4771f143ee8a" data-action="Deal Block" data-label="Accolade 1/4 Zip Pullover (Women's)" data-dimension48="Accolade 1/4 Zip Pullover (Women's)" data-dimension25="$103">View Deal</a></p></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness/alo-yogas-entire-site-is-30-percent-off-ahead-of-black-friday-here-are-my-15-favorite-deals</link>
                                                                            <description>
                            <![CDATA[ Alo Yoga deals are rare to find, but the brand's early Black Friday sale is happening now. Here are my favorite deals. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">sKsQDGURXF8gzTAAJgBkxL</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/x54Ah3ftmNYju7S6rnEXL8-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 26 Oct 2026 16:26:42 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Fitness]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Olivia Halevy ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/YAg7Fmh9dGKbg3hULBMWiU-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Olivia is a Deals Writer at Tom’s Guide. She loves all things lifestyle, shopping and sourcing the best deals from some of the top brands, retailers and websites around. From fashion and beauty to smart home and tech, she has an eye for finding practical, stylish, and reasonably-priced items that help make life simpler (and a little more aesthetically-pleasing).&amp;nbsp;Olivia has over five years of experience writing lifestyle, commerce, and branded content for &lt;a href=&quot;http://patch.com/&quot;&gt;Patch.com&lt;/a&gt;. She&#039;s covered major shopping holidays like Amazon Prime Day, Black Friday and Cyber Monday. In her free time, she enjoys trying out new exercise classes, binge-watching the latest viral TV shows, cooking, spending time with family and taking long walks with her dog, Gus.&amp;nbsp;&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/x54Ah3ftmNYju7S6rnEXL8-1920-80.jpg">
                                                            <media:credit><![CDATA[Alo / edited by Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Alo Yoga]]></media:description>                                                            <media:text><![CDATA[Alo Yoga]]></media:text>
                                <media:title type="plain"><![CDATA[Alo Yoga]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/x54Ah3ftmNYju7S6rnEXL8-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I'm a huge fan of Alo apparel. It's quickly become one of my go-to brands for working out, getting my steps in and even just lounging around the house. Their prices aren't considered cheap, but their clothes are comfortable, versatile and most importantly, they're durable. </p><p>Although the brand rarely has sales, Alo is currently hosting a <a href="https://www.aloyoga.com/?" target="_blank" rel="nofollow">huge Black Friday Early Access sale with 30% off sitewide</a>. In order to take advantage of this discount, you do have to sign up to become an Alo member, but it's free and extremely simple. (You can <a href="https://www.aloyoga.com/pages/access?" target="_blank" rel="nofollow">sign up at Alo Yoga</a>). Once you sign up, you can get 30% off literally anything you have your eyes set on.</p><p>Even better? Sale items are also slashing an extra 30% off — and my favorite deals start at just $31. We don't know how long this Early Access Sale will last, so we recommend shopping ASAP. Keep scrolling to check out my tried-and-true favorites from the sale.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><strong></strong><a href="https://www.aloyoga.com/collections/mens-sale?sort_by=PRICE_LOW_TO_HIGH" target="_blank" rel="nofollow"><strong>shop all men's Alo Yoga</strong></a><strong></strong></li><li><strong></strong><a href="https://www.aloyoga.com/collections/womens-sale-all?sort_by=PRICE_LOW_TO_HIGH" target="_blank" rel="nofollow"><strong>shop all women's Alo Yoga</strong></a><strong></strong></li><li><strong>Airlift Intrigue Bra: </strong><a href="https://www.aloyoga.com/products/w9557r-airlift-intrigue-bra-toasted-almond" target="_blank" rel="nofollow"><strong>was $78 now $31</strong></a></li><li><strong>Triumph Long Sleeve Tee: </strong><a href="https://www.aloyoga.com/products/m3079r-triumph-long-sleeve-tee-navy?" target="_blank" rel="nofollow"><strong>was $68 now $34</strong></a></li><li><strong>Airlift Redefine Bra: </strong><a href="https://www.aloyoga.com/products/w9796r-airlift-redefine-bra-black-white" target="_blank" rel="nofollow"><strong>was $88 now $44</strong></a><strong></strong></li><li><strong>Conquer Reform Mock Neck Long Sleeve: </strong><a href="https://www.aloyoga.com/products/m3218r-conquer-reform-mock-neck-long-sleeve-bone" target="_blank" rel="nofollow"><strong>was $98 now $49</strong></a><strong></strong></li><li><strong>Airlift Tennis Skirt: </strong><a href="https://www.aloyoga.com/products/w6435r-airlift-down-the-line-tennis-skirt-black" target="_blank" rel="nofollow"><strong>was $88 now $44</strong></a></li><li><strong>Alosoft Courtside Tennis Dress: </strong><a href="https://www.aloyoga.com/products/w8176r-alosoft-courtside-tennis-dress-white" target="_blank" rel="nofollow"><strong>was $118 now $47</strong></a></li><li><strong>Latitude 1/2 Zip Pullover: </strong><a href="https://www.aloyoga.com/products/m4161r-latitude-light-weight-1-2-zip-pullover-jacket-black" target="_blank" rel="nofollow"><strong>was $178 now $89</strong></a><strong></strong></li></ul><h3 class="article-body__section" id="section-best-alo-yoga-deals"><span>Best Alo Yoga Deals</span></h3><div class="product"><a data-dimension112="6a8e3f4c-d157-11f1-8710-b3c088979d80" data-action="Deal Block" data-label="Airlift Intrigue Bra (Women's)" data-dimension48="Airlift Intrigue Bra (Women's)" data-dimension25="$31" href="https://www.aloyoga.com/products/w9557r-airlift-intrigue-bra-toasted-almond" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:930px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="neAS4wnALZD9n5J3B3gd7T" name="Alo Yoga Airlift Intrigue Bra" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/neAS4wnALZD9n5J3B3gd7T-1920-80.jpg" mos="" align="middle" fullscreen="" width="930" height="1395" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/w9557r-airlift-intrigue-bra-toasted-almond" target="_blank" rel="nofollow" data-dimension112="6a8e3f4c-d157-11f1-8710-b3c088979d80" data-action="Deal Block" data-label="Airlift Intrigue Bra (Women's)" data-dimension48="Airlift Intrigue Bra (Women's)" data-dimension25="$31">Airlift Intrigue Bra (Women's): was $78 now $31</a></strong><br />The Airlift Intrigue Bra is made from Alo's signature Airlift fabric for a supportive and snug fit that's ready for everything from HIIT to headstands. (Alo recommends sizing up if you have a fuller cup size). The cut is simple but flattering, designed with a scoop-neck, adjustable straps that crisscross in back for extra lift. There's also a keyhole cutout.<a class="view-deal button" href="https://www.aloyoga.com/products/w9557r-airlift-intrigue-bra-toasted-almond" target="_blank" rel="nofollow" data-dimension112="6a8e3f4c-d157-11f1-8710-b3c088979d80" data-action="Deal Block" data-label="Airlift Intrigue Bra (Women's)" data-dimension48="Airlift Intrigue Bra (Women's)" data-dimension25="$31">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e3fc4-d157-11f1-8313-ad15c1a960be" data-action="Deal Block" data-label="Triumph Long Sleeve Tee (Men's)" data-dimension48="Triumph Long Sleeve Tee (Men's)" data-dimension25="$34" href="https://www.aloyoga.com/products/m3079r-triumph-long-sleeve-tee-navy?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="KRVhnW2jjpJGyTvpRk8pRD" name="long sleeve" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/KRVhnW2jjpJGyTvpRk8pRD-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/m3079r-triumph-long-sleeve-tee-navy?" target="_blank" rel="nofollow" data-dimension112="6a8e3fc4-d157-11f1-8313-ad15c1a960be" data-action="Deal Block" data-label="Triumph Long Sleeve Tee (Men's)" data-dimension48="Triumph Long Sleeve Tee (Men's)" data-dimension25="$34">Triumph Long Sleeve Tee (Men's): was $68 now $34</a></strong><br />You can never have enough tees — and this Alo long sleeve is airy, ultra-soft and perfect for training or layering under a light jacket. Plus, it's versatile enough that you can wear it just about anywhere. It's available in various colors.<a class="view-deal button" href="https://www.aloyoga.com/products/m3079r-triumph-long-sleeve-tee-navy?" target="_blank" rel="nofollow" data-dimension112="6a8e3fc4-d157-11f1-8313-ad15c1a960be" data-action="Deal Block" data-label="Triumph Long Sleeve Tee (Men's)" data-dimension48="Triumph Long Sleeve Tee (Men's)" data-dimension25="$34">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e403c-d157-11f1-b426-1dd511171f5a" data-action="Deal Block" data-label="Airlift Redefine Bra (Women's)" data-dimension48="Airlift Redefine Bra (Women's)" data-dimension25="$44" href="https://www.aloyoga.com/products/w9796r-airlift-redefine-bra-black-white" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:930px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="pW68i78BhEAGeRLXdzv3rB" name="Alo Yoga Airlift Redefine Bra" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pW68i78BhEAGeRLXdzv3rB-1920-80.jpg" mos="" align="middle" fullscreen="" width="930" height="1395" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/w9796r-airlift-redefine-bra-black-white" target="_blank" rel="nofollow" data-dimension112="6a8e403c-d157-11f1-b426-1dd511171f5a" data-action="Deal Block" data-label="Airlift Redefine Bra (Women's)" data-dimension48="Airlift Redefine Bra (Women's)" data-dimension25="$44">Airlift Redefine Bra (Women's): was $88 now $44</a></strong><br />The Airlift design features high-compression Airlift performance fabric, stitch lines, and corset detailing. It pairs well with the Infatuation leggings for a very cool finish. It's listed as medium support, which makes it a good option for everything from yoga to running.<a class="view-deal button" href="https://www.aloyoga.com/products/w9796r-airlift-redefine-bra-black-white" target="_blank" rel="nofollow" data-dimension112="6a8e403c-d157-11f1-b426-1dd511171f5a" data-action="Deal Block" data-label="Airlift Redefine Bra (Women's)" data-dimension48="Airlift Redefine Bra (Women's)" data-dimension25="$44">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e40b4-d157-11f1-aa15-5f5ef49a9db4" data-action="Deal Block" data-label="Airlift Down the Line Tennis Skirt (Women's)" data-dimension48="Airlift Down the Line Tennis Skirt (Women's)" data-dimension25="$44" href="https://www.aloyoga.com/products/w6435r-airlift-down-the-line-tennis-skirt-black" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:930px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="TZsSpJ3BxBmJ4ZL9FZvLXc" name="Alo Yoga Airlift Down The Line Tennis Skirt" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/TZsSpJ3BxBmJ4ZL9FZvLXc-1920-80.jpg" mos="" align="middle" fullscreen="" width="930" height="1395" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/w6435r-airlift-down-the-line-tennis-skirt-black" target="_blank" rel="nofollow" data-dimension112="6a8e40b4-d157-11f1-aa15-5f5ef49a9db4" data-action="Deal Block" data-label="Airlift Down the Line Tennis Skirt (Women's)" data-dimension48="Airlift Down the Line Tennis Skirt (Women's)" data-dimension25="$44">Airlift Down the Line Tennis Skirt (Women's): was $88 now $44</a></strong><br />This tennis skirt is made from Alo's signature Airlift fabric that provides a lightweight feel. It has detailed seams along the front for added definition along with a high-rise waist and built-in shorts (with a hidden pocket) that offers extra coverage on and off the court. <a class="view-deal button" href="https://www.aloyoga.com/products/w6435r-airlift-down-the-line-tennis-skirt-black" target="_blank" rel="nofollow" data-dimension112="6a8e40b4-d157-11f1-aa15-5f5ef49a9db4" data-action="Deal Block" data-label="Airlift Down the Line Tennis Skirt (Women's)" data-dimension48="Airlift Down the Line Tennis Skirt (Women's)" data-dimension25="$44">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e41a4-d157-11f1-9180-bbf59447b044" data-action="Deal Block" data-label="Alosoft Courtside Tennis Dress (Women's)" data-dimension48="Alosoft Courtside Tennis Dress (Women's)" data-dimension25="$47" href="https://www.aloyoga.com/products/w8176r-alosoft-courtside-tennis-dress-white" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="XKptohETcY85TbUyX5VLnX" name="alosoft" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XKptohETcY85TbUyX5VLnX-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/w8176r-alosoft-courtside-tennis-dress-white" target="_blank" rel="nofollow" data-dimension112="6a8e41a4-d157-11f1-9180-bbf59447b044" data-action="Deal Block" data-label="Alosoft Courtside Tennis Dress (Women's)" data-dimension48="Alosoft Courtside Tennis Dress (Women's)" data-dimension25="$47">Alosoft Courtside Tennis Dress (Women's): was $118 now $47</a></strong><br />This is more of a summer or warm-weather pick, but now that it's on sale, you might as well add it to your cart. This adorable tennis dress is made from Alo's signature Alosoft fabric and has a built-in onesie for all-in-one ease. It offers just the right amount of support, comfort and stretch and is perfect for any adventure.<a class="view-deal button" href="https://www.aloyoga.com/products/w8176r-alosoft-courtside-tennis-dress-white" target="_blank" rel="nofollow" data-dimension112="6a8e41a4-d157-11f1-9180-bbf59447b044" data-action="Deal Block" data-label="Alosoft Courtside Tennis Dress (Women's)" data-dimension48="Alosoft Courtside Tennis Dress (Women's)" data-dimension25="$47">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e412c-d157-11f1-9f4d-21cb954ebd0f" data-action="Deal Block" data-label="Conquer Reform Mock Neck Long Sleeve (Men's)" data-dimension48="Conquer Reform Mock Neck Long Sleeve (Men's)" data-dimension25="$49" href="https://www.aloyoga.com/products/m3218r-conquer-reform-mock-neck-long-sleeve-bone" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:930px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="mwpJoM9mJPUQGvQSzaW8P3" name="Alo Yoga Conquer Reform Mock Neck Long Sleeve" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/mwpJoM9mJPUQGvQSzaW8P3-1920-80.jpg" mos="" align="middle" fullscreen="" width="930" height="1395" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/m3218r-conquer-reform-mock-neck-long-sleeve-bone" target="_blank" rel="nofollow" data-dimension112="6a8e412c-d157-11f1-9f4d-21cb954ebd0f" data-action="Deal Block" data-label="Conquer Reform Mock Neck Long Sleeve (Men's)" data-dimension48="Conquer Reform Mock Neck Long Sleeve (Men's)" data-dimension25="$49">Conquer Reform Mock Neck Long Sleeve (Men's): was $98 now $49</a></strong><br />This Conquer Long Sleeve will leave you looking cool. It's made with Alo's signature stretchy, sweat-wicking Conquer fabric. It offers a slim fit, but it's not clingy. Plus, it'll feel ultra-soft against your skin with a cool buttery feel. <a class="view-deal button" href="https://www.aloyoga.com/products/m3218r-conquer-reform-mock-neck-long-sleeve-bone" target="_blank" rel="nofollow" data-dimension112="6a8e412c-d157-11f1-9f4d-21cb954ebd0f" data-action="Deal Block" data-label="Conquer Reform Mock Neck Long Sleeve (Men's)" data-dimension48="Conquer Reform Mock Neck Long Sleeve (Men's)" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e4212-d157-11f1-8057-03d73344435e" data-action="Deal Block" data-label="Conquer Reform Crewneck Short Sleeve (Men's)" data-dimension48="Conquer Reform Crewneck Short Sleeve (Men's)" data-dimension25="$54" href="https://www.aloyoga.com/products/m1205r-conquer-reform-crewneck-short-sleeve-black?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="SqWdyd5HuAWgavpBCsEErA" name="Alo t-shirt" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/SqWdyd5HuAWgavpBCsEErA-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/m1205r-conquer-reform-crewneck-short-sleeve-black?" target="_blank" rel="nofollow" data-dimension112="6a8e4212-d157-11f1-8057-03d73344435e" data-action="Deal Block" data-label="Conquer Reform Crewneck Short Sleeve (Men's)" data-dimension48="Conquer Reform Crewneck Short Sleeve (Men's)" data-dimension25="$54">Conquer Reform Crewneck Short Sleeve (Men's): was $78 now $54</a></strong><br />This Alo short sleeve is so versatile! It's airy, ultra-soft and perfect for training or layering under your favorite hoodie. I recommend grabbing one in several colors.<a class="view-deal button" href="https://www.aloyoga.com/products/m1205r-conquer-reform-crewneck-short-sleeve-black?" target="_blank" rel="nofollow" data-dimension112="6a8e4212-d157-11f1-8057-03d73344435e" data-action="Deal Block" data-label="Conquer Reform Crewneck Short Sleeve (Men's)" data-dimension48="Conquer Reform Crewneck Short Sleeve (Men's)" data-dimension25="$54">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e428a-d157-11f1-a682-3b05d21fb917" data-action="Deal Block" data-label="Accolade Short (Women's)" data-dimension48="Accolade Short (Women's)" data-dimension25="$54" href="https://www.aloyoga.com/products/w6472rg-accolade-short-athletic-heather-grey" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="VFMGYyj98EiJSVQw2DinSC" name="Alo Accolade shorts" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/VFMGYyj98EiJSVQw2DinSC-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/w6472rg-accolade-short-athletic-heather-grey" target="_blank" rel="nofollow" data-dimension112="6a8e428a-d157-11f1-a682-3b05d21fb917" data-action="Deal Block" data-label="Accolade Short (Women's)" data-dimension48="Accolade Short (Women's)" data-dimension25="$54">Accolade Short (Women's): was $78 now $54</a></strong><br />Elevate your loungewear collection with these super soft shorts that feature french terry fabric on the outside and warm fleece on the inside. I love wearing these cozy shorts around the house or when I'm walking my dog around the block during warmer weather. You'll definitely want to pair them with the stylish Accolade 1/4 Zip that I highlight further below. <a class="view-deal button" href="https://www.aloyoga.com/products/w6472rg-accolade-short-athletic-heather-grey" target="_blank" rel="nofollow" data-dimension112="6a8e428a-d157-11f1-a682-3b05d21fb917" data-action="Deal Block" data-label="Accolade Short (Women's)" data-dimension48="Accolade Short (Women's)" data-dimension25="$54">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e4302-d157-11f1-bef9-0f64c9ef4253" data-action="Deal Block" data-label="Airbrush Real Bra Tank (Women's)" data-dimension48="Airbrush Real Bra Tank (Women's)" data-dimension25="$54" href="https://www.aloyoga.com/products/w9587r-real-bra-tank-navy" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="YZ5EMQJNACcVfTogAGPsbU" name="Alo tank" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/YZ5EMQJNACcVfTogAGPsbU-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/w9587r-real-bra-tank-navy" target="_blank" rel="nofollow" data-dimension112="6a8e4302-d157-11f1-bef9-0f64c9ef4253" data-action="Deal Block" data-label="Airbrush Real Bra Tank (Women's)" data-dimension48="Airbrush Real Bra Tank (Women's)" data-dimension25="$54">Airbrush Real Bra Tank (Women's): was $78 now $54</a></strong><br />I can't get enough of this tank. So many fitness tanks are itchy and uncomfortable around the rib cage, but this one really does feel airbrushed with softness. I love its wide straps, flattering V-neckline and the fact that it has a built-in bra. Grab the matching yoga pants below to create your fabulous set.<a class="view-deal button" href="https://www.aloyoga.com/products/w9587r-real-bra-tank-navy" target="_blank" rel="nofollow" data-dimension112="6a8e4302-d157-11f1-bef9-0f64c9ef4253" data-action="Deal Block" data-label="Airbrush Real Bra Tank (Women's)" data-dimension48="Airbrush Real Bra Tank (Women's)" data-dimension25="$54">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e4370-d157-11f1-8070-ef5f7931ab86" data-action="Deal Block" data-label="5" Traction Shorts (Men's)" data-dimension48="5" Traction Shorts (Men's)" data-dimension25="$61" href="https://www.aloyoga.com/products/m6169r-5-traction-running-short-black" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="E2Ls8epEvgMgAdu9eiLz5G" name="Alo Yoga Traction Short" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/E2Ls8epEvgMgAdu9eiLz5G-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/m6169r-5-traction-running-short-black" target="_blank" rel="nofollow" data-dimension112="6a8e4370-d157-11f1-8070-ef5f7931ab86" data-action="Deal Block" data-label="5" Traction Shorts (Men's)" data-dimension48="5" Traction Shorts (Men's)" data-dimension25="$61">5" Traction Shorts (Men's): was $88 now $61</a></strong><br />Our Deals Editor in Chief can't recommend these shorts enough. First, they're very comfy with an elastic (but secure) waistband that stays in place even during the most intense HIIT sessions. The shorts are made of a slightly perforated, fast-drying fabric, which means they won't get heavy and weigh you down on those sweaty, humid runs. (Don't worry, they're not revealing). Are there cheaper options, yes, but these are a top choice.<a class="view-deal button" href="https://www.aloyoga.com/products/m6169r-5-traction-running-short-black" target="_blank" rel="nofollow" data-dimension112="6a8e4370-d157-11f1-8070-ef5f7931ab86" data-action="Deal Block" data-label="5" Traction Shorts (Men's)" data-dimension48="5" Traction Shorts (Men's)" data-dimension25="$61">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e43e8-d157-11f1-9cb8-4f1f4ca6232e" data-action="Deal Block" data-label="Airbrush High-Waist Highlight Goddess Legging (Women's)" data-dimension48="Airbrush High-Waist Highlight Goddess Legging (Women's)" data-dimension25="$64" href="https://www.aloyoga.com/products/w51207r-airbrush-high-waist-highlight-goddess-legging-black" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="873yoM5e6uuYF2aJS3ryiY" name="Alo deal" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/873yoM5e6uuYF2aJS3ryiY-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/w51207r-airbrush-high-waist-highlight-goddess-legging-black" target="_blank" rel="nofollow" data-dimension112="6a8e43e8-d157-11f1-9cb8-4f1f4ca6232e" data-action="Deal Block" data-label="Airbrush High-Waist Highlight Goddess Legging (Women's)" data-dimension48="Airbrush High-Waist Highlight Goddess Legging (Women's)" data-dimension25="$64">Airbrush High-Waist Highlight Goddess Legging (Women's): was $128 now $64</a></strong><br />These buttery-soft Alo leggings are supportive in all the right places, and right now, you can score 30% off in this black color. This is a total win for just under $100.<a class="view-deal button" href="https://www.aloyoga.com/products/w51207r-airbrush-high-waist-highlight-goddess-legging-black" target="_blank" rel="nofollow" data-dimension112="6a8e43e8-d157-11f1-9cb8-4f1f4ca6232e" data-action="Deal Block" data-label="Airbrush High-Waist Highlight Goddess Legging (Women's)" data-dimension48="Airbrush High-Waist Highlight Goddess Legging (Women's)" data-dimension25="$64">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e4460-d157-11f1-ba73-3b5eca588706" data-action="Deal Block" data-label="Latitude Light Weight 1/2 Zip Pullover Jacket (Men's)" data-dimension48="Latitude Light Weight 1/2 Zip Pullover Jacket (Men's)" data-dimension25="$89" href="https://www.aloyoga.com/products/m4161r-latitude-light-weight-1-2-zip-pullover-jacket-black" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:930px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="jpqrb3ejVXYMJ5LpcbTSNE" name="Alo Yoga Latitude Light Weight 1:2 Zip Pullover Jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jpqrb3ejVXYMJ5LpcbTSNE-1920-80.jpg" mos="" align="middle" fullscreen="" width="930" height="1395" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/m4161r-latitude-light-weight-1-2-zip-pullover-jacket-black" target="_blank" rel="nofollow" data-dimension112="6a8e4460-d157-11f1-ba73-3b5eca588706" data-action="Deal Block" data-label="Latitude Light Weight 1/2 Zip Pullover Jacket (Men's)" data-dimension48="Latitude Light Weight 1/2 Zip Pullover Jacket (Men's)" data-dimension25="$89">Latitude Light Weight 1/2 Zip Pullover Jacket (Men's): was $178 now $89</a></strong><br />Need a new fall jacket? This lightweight pullover is lightly filled (for a little warmth) and made from 100 percent nylon — the kind that's durable, swishy and ready to face the elements. It also has a half-zip collar, zippered side pockets, banded cuffs, and a banded hem. The fit is relaxed and comfortable.<a class="view-deal button" href="https://www.aloyoga.com/products/m4161r-latitude-light-weight-1-2-zip-pullover-jacket-black" target="_blank" rel="nofollow" data-dimension112="6a8e4460-d157-11f1-ba73-3b5eca588706" data-action="Deal Block" data-label="Latitude Light Weight 1/2 Zip Pullover Jacket (Men's)" data-dimension48="Latitude Light Weight 1/2 Zip Pullover Jacket (Men's)" data-dimension25="$89">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e45fa-d157-11f1-8d7e-8149ba49ea14" data-action="Deal Block" data-label="Airbrush High-Waist Bootcut Legging (Women's)" data-dimension48="Airbrush High-Waist Bootcut Legging (Women's)" data-dimension25="$89" href="https://www.aloyoga.com/products/w51118r-airbrush-high-waist-bootcut-legging-navy?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="Qsw5mp42qkqdNqEk5q5dBf" name="Alo yoga pant" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Qsw5mp42qkqdNqEk5q5dBf-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/w51118r-airbrush-high-waist-bootcut-legging-navy?" target="_blank" rel="nofollow" data-dimension112="6a8e45fa-d157-11f1-8d7e-8149ba49ea14" data-action="Deal Block" data-label="Airbrush High-Waist Bootcut Legging (Women's)" data-dimension48="Airbrush High-Waist Bootcut Legging (Women's)" data-dimension25="$89">Airbrush High-Waist Bootcut Legging (Women's): was $128 now $89</a></strong><br />I'm actually wearing these bootcut leggings as I write this! They are my all-time favorite legging, not only because they're comfortable, but because they're extremely flattering. I wear them literally everywhere and usually pair them with sneakers. They look great whether you're working out, walking or just want to put together a cute and casual weekend outfit. I definitely recommend these versatile leggings. <a class="view-deal button" href="https://www.aloyoga.com/products/w51118r-airbrush-high-waist-bootcut-legging-navy?" target="_blank" rel="nofollow" data-dimension112="6a8e45fa-d157-11f1-8d7e-8149ba49ea14" data-action="Deal Block" data-label="Airbrush High-Waist Bootcut Legging (Women's)" data-dimension48="Airbrush High-Waist Bootcut Legging (Women's)" data-dimension25="$89">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e467c-d157-11f1-aa03-b981bfb8fb48" data-action="Deal Block" data-label="7/8 High-Waist Airlift Legging (Women's)" data-dimension48="7/8 High-Waist Airlift Legging (Women's)" data-dimension25="$93" href="https://www.aloyoga.com/products/w5766r-7-8-high-waist-airlift-legging-black?variant=38169647710388" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="ZEAYKdVRTdVimtce8fAB2P" name="Alo leggings" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZEAYKdVRTdVimtce8fAB2P-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/w5766r-7-8-high-waist-airlift-legging-black?variant=38169647710388" target="_blank" rel="nofollow" data-dimension112="6a8e467c-d157-11f1-aa03-b981bfb8fb48" data-action="Deal Block" data-label="7/8 High-Waist Airlift Legging (Women's)" data-dimension48="7/8 High-Waist Airlift Legging (Women's)" data-dimension25="$93">7/8 High-Waist Airlift Legging (Women's): was $134 now $93</a></strong><br />These buttery-soft Alo leggings are supportive in all the right places, and right now, you can score 30% off in a rainbow of colors. This is a total win for just under $100. <a class="view-deal button" href="https://www.aloyoga.com/products/w5766r-7-8-high-waist-airlift-legging-black?variant=38169647710388" target="_blank" rel="nofollow" data-dimension112="6a8e467c-d157-11f1-aa03-b981bfb8fb48" data-action="Deal Block" data-label="7/8 High-Waist Airlift Legging (Women's)" data-dimension48="7/8 High-Waist Airlift Legging (Women's)" data-dimension25="$93">View Deal</a></p></div><div class="product"><a data-dimension112="6a8e46f4-d157-11f1-96bd-4771f143ee8a" data-action="Deal Block" data-label="Accolade 1/4 Zip Pullover (Women's)" data-dimension48="Accolade 1/4 Zip Pullover (Women's)" data-dimension25="$103" href="https://www.aloyoga.com/products/u3040rg-accolade-1-4-zip-pullover-athletic-heather-grey?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="7ffv5DbfcMMrS4QEmnYHug" name="Accolade sweathshirt" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/7ffv5DbfcMMrS4QEmnYHug-1920-80.jpg" mos="" align="middle" fullscreen="" width="750" height="1125" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.aloyoga.com/products/u3040rg-accolade-1-4-zip-pullover-athletic-heather-grey?" target="_blank" rel="nofollow" data-dimension112="6a8e46f4-d157-11f1-96bd-4771f143ee8a" data-action="Deal Block" data-label="Accolade 1/4 Zip Pullover (Women's)" data-dimension48="Accolade 1/4 Zip Pullover (Women's)" data-dimension25="$103">Accolade 1/4 Zip Pullover (Women's): was $148 now $103</a></strong><br />If you're anything like me, you'll be living in this cozy 1/4 zip. It's an absolute must for crisp spring mornings thanks to its fleece interior. It comes in a variety of colors and matches perfectly with the Accolade shorts above. It also has a <a href="https://www.aloyoga.com/products/u5012rg-accolade-straight-leg-swtpnt-athletic-heather-grey" target="_blank" rel="nofollow">matching pair of sweatpants</a> if you want to be extra warm and cozy.<a class="view-deal button" href="https://www.aloyoga.com/products/u3040rg-accolade-1-4-zip-pullover-athletic-heather-grey?" target="_blank" rel="nofollow" data-dimension112="6a8e46f4-d157-11f1-96bd-4771f143ee8a" data-action="Deal Block" data-label="Accolade 1/4 Zip Pullover (Women's)" data-dimension48="Accolade 1/4 Zip Pullover (Women's)" data-dimension25="$103">View Deal</a></p></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Stanley tumblers, mugs and bottles are on sale from $19 at Amazon — 11 early holiday deals I’d shop now ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The holidays are closer than you think! Now's a great time to start thinking about gifts — and if you're thinking the way I am, you'll want to grab some of these <a href="https://www.amazon.com/stores/page/86141DC2-87AF-4D9C-80E4-C0F22367DF0D" target="_blank" rel="nofollow">Stanley deals at Amazon</a>.</p><p>Not only are Stanley tumblers and mugs super stylish, they're also practical. They're easy to drink from and offer insulation to keep drinks at the perfect temperature.</p><p>Keep scrolling to see all my favorite deals! I also recommend checking out our <a href="https://www.tomsguide.com/coupons/amazon.com">Amazon promo codes</a> page.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><a href="https://www.amazon.com/stores/Stanley/page/47A7E765-00AF-4F34-AC01-240A7EDD822A" target="_blank" rel="nofollow"><strong>shop all Stanley deals at Amazon</strong></a></li><li><strong>Quencher H2.0 FlowState Tumbler (14 oz): </strong><a href="https://www.amazon.com/Quencher-FlowState-Stainless-Insulated-Smoothie/dp/B0CP9Z16VD" target="_blank" rel="nofollow"><strong>was $25 now $19</strong></a></li><li><strong>Cafe-To-Go Travel Mug (16 oz): </strong><a href="https://www.amazon.com/STANLEY-Leakproof-Two-Part-Insulated-Stainless/dp/B0DXNC34LQ" target="_blank" rel="nofollow"><strong>was $28 now $19</strong></a></li><li><strong>Classic Food Jar and Spork (14 oz): </strong><a href="https://www.amazon.com/STANLEY-Insulated-Container-Stainless-Leakproof/dp/B0H1YLQ21Q" target="_blank" rel="nofollow"><strong>was $30 now $25</strong></a></li><li><strong>IceFlow 2.0 Flip Straw Tumbler (30 oz): </strong><a href="https://www.amazon.com/STANLEY-Champagne-Resistant-Insulated-Stainless/dp/B0H48S2D7V" target="_blank" rel="nofollow"><strong>was $35 now $26</strong></a></li><li><strong>Classic Legendary Vacuum Bottle: </strong><a href="https://www.amazon.com/Legendary-Leakproof-Insulated-Stainless-Hammertone/dp/B0BRKQDYTV" target="_blank" rel="nofollow"><strong>was $45 now $29</strong></a></li><li><strong>IceFlow Flip Straw 2.0 Water Bottle (36 oz): </strong><a href="https://www.amazon.com/Lightweight-Leak-Resistant-Insulated-Stainless-BPA-Free/dp/B0CYVRB35T" target="_blank" rel="nofollow"><strong>was $45 now $42</strong></a></li><li><strong>IceFlow Flip Straw Jug with Handle (40 oz): </strong><a href="https://www.amazon.com/Stanley-IceFlow-Stainless-Steel-Tumbler/dp/B0CT4BJ4Q1" target="_blank" rel="nofollow"><strong>was $69 now $57</strong></a></li></ul><h3 class="article-body__section" id="section-best-stanley-deals"><span>Best Stanley Deals</span></h3><div class="product"><a data-dimension112="f4cca5c0-d140-11f1-9ddd-89e84a606cde" data-action="Deal Block" data-label="Quencher H2.0 FlowState (14 oz)" data-dimension48="Quencher H2.0 FlowState (14 oz)" data-dimension25="$19" href="https://www.amazon.com/Quencher-FlowState-Stainless-Insulated-Smoothie/dp/B0CP9Z16VD" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:503px;"><p class="vanilla-image-block" style="padding-top:293.64%;"><img id="phYEdy8ndMPk2atezwdctd" name="Stanley quencher" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/phYEdy8ndMPk2atezwdctd-1920-80.jpg" mos="" align="middle" fullscreen="" width="503" height="1477" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Quencher-FlowState-Stainless-Insulated-Smoothie/dp/B0CP9Z16VD" target="_blank" rel="nofollow" data-dimension112="f4cca5c0-d140-11f1-9ddd-89e84a606cde" data-action="Deal Block" data-label="Quencher H2.0 FlowState (14 oz)" data-dimension48="Quencher H2.0 FlowState (14 oz)" data-dimension25="$19">Quencher H2.0 FlowState (14 oz): was $25 now $19</a></strong><br />With the Stanley Quencher love still going strong, it can be difficult to secure a discount on this incredibly popular tumbler. But right now you can save on the 14 oz version of the trendy beverage container.<a class="view-deal button" href="https://www.amazon.com/Quencher-FlowState-Stainless-Insulated-Smoothie/dp/B0CP9Z16VD" target="_blank" rel="nofollow" data-dimension112="f4cca5c0-d140-11f1-9ddd-89e84a606cde" data-action="Deal Block" data-label="Quencher H2.0 FlowState (14 oz)" data-dimension48="Quencher H2.0 FlowState (14 oz)" data-dimension25="$19">View Deal</a></p></div><div class="product"><a data-dimension112="f4cca624-d140-11f1-a283-fd1d73cdbb35" data-action="Deal Block" data-label="Cafe-To-Go Travel Mug (16 oz)" data-dimension48="Cafe-To-Go Travel Mug (16 oz)" data-dimension25="$19" href="https://www.amazon.com/STANLEY-Leakproof-Two-Part-Insulated-Stainless/dp/B0DXNC34LQ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:510px;"><p class="vanilla-image-block" style="padding-top:294.12%;"><img id="FhHs5uZirZNJVWDMXzDeqA" name="Cafe-To-Go Travel Mug (16 oz)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/FhHs5uZirZNJVWDMXzDeqA-1920-80.jpg" mos="" align="middle" fullscreen="" width="510" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/STANLEY-Leakproof-Two-Part-Insulated-Stainless/dp/B0DXNC34LQ" target="_blank" rel="nofollow" data-dimension112="f4cca624-d140-11f1-a283-fd1d73cdbb35" data-action="Deal Block" data-label="Cafe-To-Go Travel Mug (16 oz)" data-dimension48="Cafe-To-Go Travel Mug (16 oz)" data-dimension25="$19">Cafe-To-Go Travel Mug (16 oz): was $28 now $19</a></strong><br />This Stanley is here to make a case for the last coffee mug you ever need to buy. It'll keep your coffee hot for up to 6 hours, and offers two different sipping styles with its dual openings.<a class="view-deal button" href="https://www.amazon.com/STANLEY-Leakproof-Two-Part-Insulated-Stainless/dp/B0DXNC34LQ" target="_blank" rel="nofollow" data-dimension112="f4cca624-d140-11f1-a283-fd1d73cdbb35" data-action="Deal Block" data-label="Cafe-To-Go Travel Mug (16 oz)" data-dimension48="Cafe-To-Go Travel Mug (16 oz)" data-dimension25="$19">View Deal</a></p></div><div class="product"><a data-dimension112="f4cca6e2-d140-11f1-be0c-ede6ae697bfc" data-action="Deal Block" data-label="Classic Food Jar and Spork (14 oz)" data-dimension48="Classic Food Jar and Spork (14 oz)" data-dimension25="$25" href="https://www.amazon.com/STANLEY-Insulated-Container-Stainless-Leakproof/dp/B0H1YLQ21Q" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1010px;"><p class="vanilla-image-block" style="padding-top:144.36%;"><img id="ojbwzuMy3D67RHPAqD2pUU" name="Classic Food Jar and Spork (14 oz)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ojbwzuMy3D67RHPAqD2pUU-1920-80.jpg" mos="" align="middle" fullscreen="" width="1010" height="1458" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/STANLEY-Insulated-Container-Stainless-Leakproof/dp/B0H1YLQ21Q" target="_blank" rel="nofollow" data-dimension112="f4cca6e2-d140-11f1-be0c-ede6ae697bfc" data-action="Deal Block" data-label="Classic Food Jar and Spork (14 oz)" data-dimension48="Classic Food Jar and Spork (14 oz)" data-dimension25="$25">Classic Food Jar and Spork (14 oz): was $30 now $25</a></strong><br />This Stanley thermos with an integrated spork is designed with a leakproof lid and can hold your favorite foods when you're on the go. Regardless of the temperature outside, it keeps food hot or cold for 7 hours. It seals tight and features a wide mouth, making it easy to clean.<a class="view-deal button" href="https://www.amazon.com/STANLEY-Insulated-Container-Stainless-Leakproof/dp/B0H1YLQ21Q" target="_blank" rel="nofollow" data-dimension112="f4cca6e2-d140-11f1-be0c-ede6ae697bfc" data-action="Deal Block" data-label="Classic Food Jar and Spork (14 oz)" data-dimension48="Classic Food Jar and Spork (14 oz)" data-dimension25="$25">View Deal</a></p></div><div class="product"><a data-dimension112="731d8786-d14c-11f1-8eaf-793a3c91dbc4" data-action="Deal Block" data-label="IceFlow Cap and Carry Water Bottle (16 oz)" data-dimension48="IceFlow Cap and Carry Water Bottle (16 oz)" data-dimension25="$25" href="https://www.amazon.com/Lightweight-Leakproof-Insulated-Stainless-BPA-Free/dp/B0CHN7KDNZ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:253px;"><p class="vanilla-image-block" style="padding-top:347.43%;"><img id="fL7dCo8ZNJKibWdUGa9Jzm" name="Stanley IceFlow Cap and Carry Water Bottle.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/fL7dCo8ZNJKibWdUGa9Jzm-1920-80.jpg" mos="" align="middle" fullscreen="" width="253" height="879" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Lightweight-Leakproof-Insulated-Stainless-BPA-Free/dp/B0CHN7KDNZ" target="_blank" rel="nofollow" data-dimension112="731d8786-d14c-11f1-8eaf-793a3c91dbc4" data-action="Deal Block" data-label="IceFlow Cap and Carry Water Bottle (16 oz)" data-dimension48="IceFlow Cap and Carry Water Bottle (16 oz)" data-dimension25="$25">IceFlow Cap and Carry Water Bottle (16 oz): was $35 now $25</a></strong><br />Not a fan of straws or chug lids? The Stanley IceFlow Cap and Carry Water Bottle has a twist lid that's easy to access thanks to its large, chunky handle. What's more, that handle on top means you can carry it at by your side without it spilling. Like many Stanley cups, it's insulated to keep your drinks at their optimum temperature and it fits in most car cup holders.<a class="view-deal button" href="https://www.amazon.com/Lightweight-Leakproof-Insulated-Stainless-BPA-Free/dp/B0CHN7KDNZ" target="_blank" rel="nofollow" data-dimension112="731d8786-d14c-11f1-8eaf-793a3c91dbc4" data-action="Deal Block" data-label="IceFlow Cap and Carry Water Bottle (16 oz)" data-dimension48="IceFlow Cap and Carry Water Bottle (16 oz)" data-dimension25="$25">View Deal</a></p></div><div class="product"><a data-dimension112="f4cca750-d140-11f1-9c80-2f0de7014751" data-action="Deal Block" data-label="IceFlow 2.0 Flip Straw Tumbler (30 oz)" data-dimension48="IceFlow 2.0 Flip Straw Tumbler (30 oz)" data-dimension25="$26" href="https://www.amazon.com/STANLEY-Champagne-Resistant-Insulated-Stainless/dp/B0H48S2D7V" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:487px;"><p class="vanilla-image-block" style="padding-top:299.59%;"><img id="jfyqVfb82F2gre6soyu7ab" name="IceFlow 2.0 Flip Straw Tumbler (30 oz)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jfyqVfb82F2gre6soyu7ab-1920-80.jpg" mos="" align="middle" fullscreen="" width="487" height="1459" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/STANLEY-Champagne-Resistant-Insulated-Stainless/dp/B0H48S2D7V" target="_blank" rel="nofollow" data-dimension112="f4cca750-d140-11f1-9c80-2f0de7014751" data-action="Deal Block" data-label="IceFlow 2.0 Flip Straw Tumbler (30 oz)" data-dimension48="IceFlow 2.0 Flip Straw Tumbler (30 oz)" data-dimension25="$26">IceFlow 2.0 Flip Straw Tumbler (30 oz): was $35 now $26</a></strong><br />This Stanley features a 30oz capacity, a handle for transportation and a flip straw for easy sipping. The insulation can keep your drinks icy for up to 2 days.<a class="view-deal button" href="https://www.amazon.com/STANLEY-Champagne-Resistant-Insulated-Stainless/dp/B0H48S2D7V" target="_blank" rel="nofollow" data-dimension112="f4cca750-d140-11f1-9c80-2f0de7014751" data-action="Deal Block" data-label="IceFlow 2.0 Flip Straw Tumbler (30 oz)" data-dimension48="IceFlow 2.0 Flip Straw Tumbler (30 oz)" data-dimension25="$26">View Deal</a></p></div><div class="product"><a data-dimension112="f4cca7aa-d140-11f1-aabd-63c300e2883a" data-action="Deal Block" data-label="Classic Legendary Vacuum Bottle" data-dimension48="Classic Legendary Vacuum Bottle" data-dimension25="$29" href="https://www.amazon.com/Legendary-Leakproof-Insulated-Stainless-Hammertone/dp/B0BRKQDYTV" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:486px;"><p class="vanilla-image-block" style="padding-top:308.64%;"><img id="PRUhUxKXFDy7LbPYyKEiDi" name="Classic Legendary Vacuum Bottle" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/PRUhUxKXFDy7LbPYyKEiDi-1920-80.jpg" mos="" align="middle" fullscreen="" width="486" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Legendary-Leakproof-Insulated-Stainless-Hammertone/dp/B0BRKQDYTV" target="_blank" rel="nofollow" data-dimension112="f4cca7aa-d140-11f1-aabd-63c300e2883a" data-action="Deal Block" data-label="Classic Legendary Vacuum Bottle" data-dimension48="Classic Legendary Vacuum Bottle" data-dimension25="$29">Classic Legendary Vacuum Bottle: was $45 now $29</a></strong><br />Don't miss your chance to grab this Stanley deal — it's called a classic for a reason. Perfect for coffee, tea and even soup, this vacuum bottle comes with a mug for easy serving.<a class="view-deal button" href="https://www.amazon.com/Legendary-Leakproof-Insulated-Stainless-Hammertone/dp/B0BRKQDYTV" target="_blank" rel="nofollow" data-dimension112="f4cca7aa-d140-11f1-aabd-63c300e2883a" data-action="Deal Block" data-label="Classic Legendary Vacuum Bottle" data-dimension48="Classic Legendary Vacuum Bottle" data-dimension25="$29">View Deal</a></p></div><div class="product"><a data-dimension112="f4cca872-d140-11f1-9ea2-a3c63f11dc1a" data-action="Deal Block" data-label="IceFlow Fast Flow Water Bottle (24 oz)" data-dimension48="IceFlow Fast Flow Water Bottle (24 oz)" data-dimension25="$32" href="https://www.amazon.com/Lightweight-Leakproof-Insulated-Stainless-BPA-Free/dp/B0CFNRCVF8" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:316px;"><p class="vanilla-image-block" style="padding-top:278.16%;"><img id="ssCbmwVVnEcqjXw7DyC8F" name="Stanley Fast Flow.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ssCbmwVVnEcqjXw7DyC8F-1920-80.jpg" mos="" align="middle" fullscreen="" width="316" height="879" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Lightweight-Leakproof-Insulated-Stainless-BPA-Free/dp/B0CFNRCVF8" target="_blank" rel="nofollow" data-dimension112="f4cca872-d140-11f1-9ea2-a3c63f11dc1a" data-action="Deal Block" data-label="IceFlow Fast Flow Water Bottle (24 oz)" data-dimension48="IceFlow Fast Flow Water Bottle (24 oz)" data-dimension25="$32">IceFlow Fast Flow Water Bottle (24 oz): was $35 now $32</a></strong><br />This lightweight water bottle was designed to carry the most amount of water without weighing you down. Perfect for sipping during workouts, on your daily commute and camping trips, the bottle has a wide mouth opening that allows you to quench your thirst quickly. It's available in a variety of vibrant hues and four different sizes. <a class="view-deal button" href="https://www.amazon.com/Lightweight-Leakproof-Insulated-Stainless-BPA-Free/dp/B0CFNRCVF8" target="_blank" rel="nofollow" data-dimension112="f4cca872-d140-11f1-9ea2-a3c63f11dc1a" data-action="Deal Block" data-label="IceFlow Fast Flow Water Bottle (24 oz)" data-dimension48="IceFlow Fast Flow Water Bottle (24 oz)" data-dimension25="$32">View Deal</a></p></div><div class="product"><a data-dimension112="f4cca8d6-d140-11f1-8a3f-8761188c4a86" data-action="Deal Block" data-label="Quencher ProTour Flipstraw Tumbler (40 oz)" data-dimension48="Quencher ProTour Flipstraw Tumbler (40 oz)" data-dimension25="$33" href="https://www.amazon.com/STANLEY-Leakproof-Cupholder-Compatible-Insulated/dp/B0G77P82ZT" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:784px;"><p class="vanilla-image-block" style="padding-top:186.10%;"><img id="8KeoEbWJrTGTCHq4axhjtL" name="Quencher ProTour Flipstraw Tumbler (40 oz)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/8KeoEbWJrTGTCHq4axhjtL-1920-80.jpg" mos="" align="middle" fullscreen="" width="784" height="1459" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/STANLEY-Leakproof-Cupholder-Compatible-Insulated/dp/B0G77P82ZT" target="_blank" rel="nofollow" data-dimension112="f4cca8d6-d140-11f1-8a3f-8761188c4a86" data-action="Deal Block" data-label="Quencher ProTour Flipstraw Tumbler (40 oz)" data-dimension48="Quencher ProTour Flipstraw Tumbler (40 oz)" data-dimension25="$33">Quencher ProTour Flipstraw Tumbler (40 oz): was $45 now $33</a></strong><br />This Stanley tumbler lets you sip without worry thanks to its flip straw lid. All you have to do is flip up the built-in straw for a quick drink, then snap it shut to prevent any spills. Designed to fit in a car cup holder, you'll be able to take it with you on all adventures and it can keep your drinks hot or cold for hours thanks to its double walled insulation.<a class="view-deal button" href="https://www.amazon.com/STANLEY-Leakproof-Cupholder-Compatible-Insulated/dp/B0G77P82ZT" target="_blank" rel="nofollow" data-dimension112="f4cca8d6-d140-11f1-8a3f-8761188c4a86" data-action="Deal Block" data-label="Quencher ProTour Flipstraw Tumbler (40 oz)" data-dimension48="Quencher ProTour Flipstraw Tumbler (40 oz)" data-dimension25="$33">View Deal</a></p></div><div class="product"><a data-dimension112="f4cca93a-d140-11f1-96f4-f1b1cbee777c" data-action="Deal Block" data-label="Quencher H2.0 Tumbler (40 oz)" data-dimension48="Quencher H2.0 Tumbler (40 oz)" data-dimension25="$34" href="https://www.amazon.com/STANLEY-Flowstate-3-Position-Compatible-Insulated/dp/B0CP9Y2SKW" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:400px;"><p class="vanilla-image-block" style="padding-top:219.75%;"><img id="ho8fBjchigjZLwpGRcTDCn" name="Stanley sage" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ho8fBjchigjZLwpGRcTDCn-1920-80.jpg" mos="" align="middle" fullscreen="" width="400" height="879" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/STANLEY-Flowstate-3-Position-Compatible-Insulated/dp/B0CP9Y2SKW" target="_blank" rel="nofollow" data-dimension112="f4cca93a-d140-11f1-96f4-f1b1cbee777c" data-action="Deal Block" data-label="Quencher H2.0 Tumbler (40 oz)" data-dimension48="Quencher H2.0 Tumbler (40 oz)" data-dimension25="$34">Quencher H2.0 Tumbler (40 oz): was $45 now $34</a></strong><br />Looking for something large to hold your beverages? The popular 40-ounce Stanley Quencher H2.0 Tumbler fits into most car cup holders. It's made with recycled stainless steel, features a 3-position lid, and reusable straw. Its double-wall vacuum insulation can keep water ice cold for 40 hours. <a class="view-deal button" href="https://www.amazon.com/STANLEY-Flowstate-3-Position-Compatible-Insulated/dp/B0CP9Y2SKW" target="_blank" rel="nofollow" data-dimension112="f4cca93a-d140-11f1-96f4-f1b1cbee777c" data-action="Deal Block" data-label="Quencher H2.0 Tumbler (40 oz)" data-dimension48="Quencher H2.0 Tumbler (40 oz)" data-dimension25="$34">View Deal</a></p></div><div class="product"><a data-dimension112="f4cca99e-d140-11f1-b20d-b50ed10b632e" data-action="Deal Block" data-label="IceFlow Flip Straw 2.0 Water Bottle (36 oz)" data-dimension48="IceFlow Flip Straw 2.0 Water Bottle (36 oz)" data-dimension25="$42" href="https://www.amazon.com/Lightweight-Leak-Resistant-Insulated-Stainless-BPA-Free/dp/B0CYVRB35T" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:493px;"><p class="vanilla-image-block" style="padding-top:304.26%;"><img id="srCGwMucdiuWiGjkM6xtK4" name="51Y0idpsdWL._AC_SL1500_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/srCGwMucdiuWiGjkM6xtK4-1920-80.jpg" mos="" align="middle" fullscreen="" width="493" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Lightweight-Leak-Resistant-Insulated-Stainless-BPA-Free/dp/B0CYVRB35T" target="_blank" rel="nofollow" data-dimension112="f4cca99e-d140-11f1-b20d-b50ed10b632e" data-action="Deal Block" data-label="IceFlow Flip Straw 2.0 Water Bottle (36 oz)" data-dimension48="IceFlow Flip Straw 2.0 Water Bottle (36 oz)" data-dimension25="$42">IceFlow Flip Straw 2.0 Water Bottle (36 oz): was $45 now $42</a></strong><br />Made with AeroLight spun steel, Stanley bills the IceFlow Flip Straw 2.0 Water Bottle as being 33% lighter than other stainless steel water bottles. That makes it super easy to take around with you, and the Flip Straw lid makes it super easy to sip from too.<a class="view-deal button" href="https://www.amazon.com/Lightweight-Leak-Resistant-Insulated-Stainless-BPA-Free/dp/B0CYVRB35T" target="_blank" rel="nofollow" data-dimension112="f4cca99e-d140-11f1-b20d-b50ed10b632e" data-action="Deal Block" data-label="IceFlow Flip Straw 2.0 Water Bottle (36 oz)" data-dimension48="IceFlow Flip Straw 2.0 Water Bottle (36 oz)" data-dimension25="$42">View Deal</a></p></div><div class="product"><a data-dimension112="f4ccaa0c-d140-11f1-b398-8333244e253c" data-action="Deal Block" data-label="IceFlow Flip Straw Jug with Handle (40 oz)" data-dimension48="IceFlow Flip Straw Jug with Handle (40 oz)" data-dimension25="$57" href="https://www.amazon.com/Stanley-IceFlow-Stainless-Steel-Tumbler/dp/B0CT4BJ4Q1" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:702px;"><p class="vanilla-image-block" style="padding-top:213.68%;"><img id="yYqTMUAPSrnqJ4EKwXCMLC" name="61MXE5ctmHL._AC_SL1500_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/yYqTMUAPSrnqJ4EKwXCMLC-1920-80.jpg" mos="" align="middle" fullscreen="" width="702" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Stanley-IceFlow-Stainless-Steel-Tumbler/dp/B0CT4BJ4Q1" target="_blank" rel="nofollow" data-dimension112="f4ccaa0c-d140-11f1-b398-8333244e253c" data-action="Deal Block" data-label="IceFlow Flip Straw Jug with Handle (40 oz)" data-dimension48="IceFlow Flip Straw Jug with Handle (40 oz)" data-dimension25="$57">IceFlow Flip Straw Jug with Handle (40 oz): was $69 now $57</a></strong><br />While this water jug is the smallest of its family from Stanley, it still houses an impressive 40 oz of water. It'll keep your cold drinks cold for up to 14 hours, while having a sweat-proof coating that's perfect for trips to the gym. And when you're done drinking, just pop it in the dishwasher to clean.<a class="view-deal button" href="https://www.amazon.com/Stanley-IceFlow-Stainless-Steel-Tumbler/dp/B0CT4BJ4Q1" target="_blank" rel="nofollow" data-dimension112="f4ccaa0c-d140-11f1-b398-8333244e253c" data-action="Deal Block" data-label="IceFlow Flip Straw Jug with Handle (40 oz)" data-dimension48="IceFlow Flip Straw Jug with Handle (40 oz)" data-dimension25="$57">View Deal</a></p></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness/stanley-tumblers-mugs-and-bottles-are-on-sale-from-usd19-at-amazon-11-early-holiday-deals-id-shop-now</link>
                                                                            <description>
                            <![CDATA[ I'm sharing the best Stanley deals to shop ahead of the holidays — treat you and your loved ones to some stylish new drinkware. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">XJEFgVyUCUuthDxebfikZm</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/tas2LcwBqZePVhW8GoFdci-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 26 Oct 2026 14:52:27 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Fitness]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                <author><![CDATA[ millie.daviswilliams@futurenet.com (Millie Davis-Williams) ]]></author>                    <dc:creator><![CDATA[ Millie Davis-Williams ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/WU6pa7hKuxs5ScCoqcXYWA-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Millie is a Deals Editor at Tom&#039;s Guide specializing in tech deals content. Based in London, Millie has spent a lifetime stubbornly refusing to pay full price on any possible purchase. She has years of searching for the best discounts on the latest and greatest phones, TVs and gadgets under her belt, and knows how to sort the best deals from the rest. Helping readers save on the products they want is her mission, whether it’s an Apple Watch or a new tablet.&lt;/p&gt;&lt;p&gt;Since working at Tom’s Guide, Millie has covered retail events like Prime Day, Black Friday and Cyber Monday extensively, meaning she knows the products readers are looking for and the best times of year to hit “purchase.”&lt;/p&gt;&lt;p&gt;When she’s not looking for discounts, Millie covers news and writes how-to articles about everything from phones, streaming devices, and headphones to apps and video games.&lt;/p&gt;&lt;p&gt;In her spare time, Millie enjoys reading, gaming on her Nintendo Switch and creating digital art. She’s also a fan of watching Disney movies and collecting plush (the latter having totally taken over her bedroom.)&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/tas2LcwBqZePVhW8GoFdci-1920-80.jpg">
                                                            <media:credit><![CDATA[Stanley / Edited by Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Stanley drinkware]]></media:description>                                                            <media:text><![CDATA[Stanley drinkware]]></media:text>
                                <media:title type="plain"><![CDATA[Stanley drinkware]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/tas2LcwBqZePVhW8GoFdci-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The holidays are closer than you think! Now's a great time to start thinking about gifts — and if you're thinking the way I am, you'll want to grab some of these <a href="https://www.amazon.com/stores/page/86141DC2-87AF-4D9C-80E4-C0F22367DF0D" target="_blank" rel="nofollow">Stanley deals at Amazon</a>.</p><p>Not only are Stanley tumblers and mugs super stylish, they're also practical. They're easy to drink from and offer insulation to keep drinks at the perfect temperature.</p><p>Keep scrolling to see all my favorite deals! I also recommend checking out our <a href="https://www.tomsguide.com/coupons/amazon.com">Amazon promo codes</a> page.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><a href="https://www.amazon.com/stores/Stanley/page/47A7E765-00AF-4F34-AC01-240A7EDD822A" target="_blank" rel="nofollow"><strong>shop all Stanley deals at Amazon</strong></a></li><li><strong>Quencher H2.0 FlowState Tumbler (14 oz): </strong><a href="https://www.amazon.com/Quencher-FlowState-Stainless-Insulated-Smoothie/dp/B0CP9Z16VD" target="_blank" rel="nofollow"><strong>was $25 now $19</strong></a></li><li><strong>Cafe-To-Go Travel Mug (16 oz): </strong><a href="https://www.amazon.com/STANLEY-Leakproof-Two-Part-Insulated-Stainless/dp/B0DXNC34LQ" target="_blank" rel="nofollow"><strong>was $28 now $19</strong></a></li><li><strong>Classic Food Jar and Spork (14 oz): </strong><a href="https://www.amazon.com/STANLEY-Insulated-Container-Stainless-Leakproof/dp/B0H1YLQ21Q" target="_blank" rel="nofollow"><strong>was $30 now $25</strong></a></li><li><strong>IceFlow 2.0 Flip Straw Tumbler (30 oz): </strong><a href="https://www.amazon.com/STANLEY-Champagne-Resistant-Insulated-Stainless/dp/B0H48S2D7V" target="_blank" rel="nofollow"><strong>was $35 now $26</strong></a></li><li><strong>Classic Legendary Vacuum Bottle: </strong><a href="https://www.amazon.com/Legendary-Leakproof-Insulated-Stainless-Hammertone/dp/B0BRKQDYTV" target="_blank" rel="nofollow"><strong>was $45 now $29</strong></a></li><li><strong>IceFlow Flip Straw 2.0 Water Bottle (36 oz): </strong><a href="https://www.amazon.com/Lightweight-Leak-Resistant-Insulated-Stainless-BPA-Free/dp/B0CYVRB35T" target="_blank" rel="nofollow"><strong>was $45 now $42</strong></a></li><li><strong>IceFlow Flip Straw Jug with Handle (40 oz): </strong><a href="https://www.amazon.com/Stanley-IceFlow-Stainless-Steel-Tumbler/dp/B0CT4BJ4Q1" target="_blank" rel="nofollow"><strong>was $69 now $57</strong></a></li></ul><h3 class="article-body__section" id="section-best-stanley-deals"><span>Best Stanley Deals</span></h3><div class="product"><a data-dimension112="f4cca5c0-d140-11f1-9ddd-89e84a606cde" data-action="Deal Block" data-label="Quencher H2.0 FlowState (14 oz)" data-dimension48="Quencher H2.0 FlowState (14 oz)" data-dimension25="$19" href="https://www.amazon.com/Quencher-FlowState-Stainless-Insulated-Smoothie/dp/B0CP9Z16VD" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:503px;"><p class="vanilla-image-block" style="padding-top:293.64%;"><img id="phYEdy8ndMPk2atezwdctd" name="Stanley quencher" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/phYEdy8ndMPk2atezwdctd-1920-80.jpg" mos="" align="middle" fullscreen="" width="503" height="1477" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Quencher-FlowState-Stainless-Insulated-Smoothie/dp/B0CP9Z16VD" target="_blank" rel="nofollow" data-dimension112="f4cca5c0-d140-11f1-9ddd-89e84a606cde" data-action="Deal Block" data-label="Quencher H2.0 FlowState (14 oz)" data-dimension48="Quencher H2.0 FlowState (14 oz)" data-dimension25="$19">Quencher H2.0 FlowState (14 oz): was $25 now $19</a></strong><br />With the Stanley Quencher love still going strong, it can be difficult to secure a discount on this incredibly popular tumbler. But right now you can save on the 14 oz version of the trendy beverage container.<a class="view-deal button" href="https://www.amazon.com/Quencher-FlowState-Stainless-Insulated-Smoothie/dp/B0CP9Z16VD" target="_blank" rel="nofollow" data-dimension112="f4cca5c0-d140-11f1-9ddd-89e84a606cde" data-action="Deal Block" data-label="Quencher H2.0 FlowState (14 oz)" data-dimension48="Quencher H2.0 FlowState (14 oz)" data-dimension25="$19">View Deal</a></p></div><div class="product"><a data-dimension112="f4cca624-d140-11f1-a283-fd1d73cdbb35" data-action="Deal Block" data-label="Cafe-To-Go Travel Mug (16 oz)" data-dimension48="Cafe-To-Go Travel Mug (16 oz)" data-dimension25="$19" href="https://www.amazon.com/STANLEY-Leakproof-Two-Part-Insulated-Stainless/dp/B0DXNC34LQ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:510px;"><p class="vanilla-image-block" style="padding-top:294.12%;"><img id="FhHs5uZirZNJVWDMXzDeqA" name="Cafe-To-Go Travel Mug (16 oz)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/FhHs5uZirZNJVWDMXzDeqA-1920-80.jpg" mos="" align="middle" fullscreen="" width="510" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/STANLEY-Leakproof-Two-Part-Insulated-Stainless/dp/B0DXNC34LQ" target="_blank" rel="nofollow" data-dimension112="f4cca624-d140-11f1-a283-fd1d73cdbb35" data-action="Deal Block" data-label="Cafe-To-Go Travel Mug (16 oz)" data-dimension48="Cafe-To-Go Travel Mug (16 oz)" data-dimension25="$19">Cafe-To-Go Travel Mug (16 oz): was $28 now $19</a></strong><br />This Stanley is here to make a case for the last coffee mug you ever need to buy. It'll keep your coffee hot for up to 6 hours, and offers two different sipping styles with its dual openings.<a class="view-deal button" href="https://www.amazon.com/STANLEY-Leakproof-Two-Part-Insulated-Stainless/dp/B0DXNC34LQ" target="_blank" rel="nofollow" data-dimension112="f4cca624-d140-11f1-a283-fd1d73cdbb35" data-action="Deal Block" data-label="Cafe-To-Go Travel Mug (16 oz)" data-dimension48="Cafe-To-Go Travel Mug (16 oz)" data-dimension25="$19">View Deal</a></p></div><div class="product"><a data-dimension112="f4cca6e2-d140-11f1-be0c-ede6ae697bfc" data-action="Deal Block" data-label="Classic Food Jar and Spork (14 oz)" data-dimension48="Classic Food Jar and Spork (14 oz)" data-dimension25="$25" href="https://www.amazon.com/STANLEY-Insulated-Container-Stainless-Leakproof/dp/B0H1YLQ21Q" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1010px;"><p class="vanilla-image-block" style="padding-top:144.36%;"><img id="ojbwzuMy3D67RHPAqD2pUU" name="Classic Food Jar and Spork (14 oz)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ojbwzuMy3D67RHPAqD2pUU-1920-80.jpg" mos="" align="middle" fullscreen="" width="1010" height="1458" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/STANLEY-Insulated-Container-Stainless-Leakproof/dp/B0H1YLQ21Q" target="_blank" rel="nofollow" data-dimension112="f4cca6e2-d140-11f1-be0c-ede6ae697bfc" data-action="Deal Block" data-label="Classic Food Jar and Spork (14 oz)" data-dimension48="Classic Food Jar and Spork (14 oz)" data-dimension25="$25">Classic Food Jar and Spork (14 oz): was $30 now $25</a></strong><br />This Stanley thermos with an integrated spork is designed with a leakproof lid and can hold your favorite foods when you're on the go. Regardless of the temperature outside, it keeps food hot or cold for 7 hours. It seals tight and features a wide mouth, making it easy to clean.<a class="view-deal button" href="https://www.amazon.com/STANLEY-Insulated-Container-Stainless-Leakproof/dp/B0H1YLQ21Q" target="_blank" rel="nofollow" data-dimension112="f4cca6e2-d140-11f1-be0c-ede6ae697bfc" data-action="Deal Block" data-label="Classic Food Jar and Spork (14 oz)" data-dimension48="Classic Food Jar and Spork (14 oz)" data-dimension25="$25">View Deal</a></p></div><div class="product"><a data-dimension112="731d8786-d14c-11f1-8eaf-793a3c91dbc4" data-action="Deal Block" data-label="IceFlow Cap and Carry Water Bottle (16 oz)" data-dimension48="IceFlow Cap and Carry Water Bottle (16 oz)" data-dimension25="$25" href="https://www.amazon.com/Lightweight-Leakproof-Insulated-Stainless-BPA-Free/dp/B0CHN7KDNZ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:253px;"><p class="vanilla-image-block" style="padding-top:347.43%;"><img id="fL7dCo8ZNJKibWdUGa9Jzm" name="Stanley IceFlow Cap and Carry Water Bottle.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/fL7dCo8ZNJKibWdUGa9Jzm-1920-80.jpg" mos="" align="middle" fullscreen="" width="253" height="879" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Lightweight-Leakproof-Insulated-Stainless-BPA-Free/dp/B0CHN7KDNZ" target="_blank" rel="nofollow" data-dimension112="731d8786-d14c-11f1-8eaf-793a3c91dbc4" data-action="Deal Block" data-label="IceFlow Cap and Carry Water Bottle (16 oz)" data-dimension48="IceFlow Cap and Carry Water Bottle (16 oz)" data-dimension25="$25">IceFlow Cap and Carry Water Bottle (16 oz): was $35 now $25</a></strong><br />Not a fan of straws or chug lids? The Stanley IceFlow Cap and Carry Water Bottle has a twist lid that's easy to access thanks to its large, chunky handle. What's more, that handle on top means you can carry it at by your side without it spilling. Like many Stanley cups, it's insulated to keep your drinks at their optimum temperature and it fits in most car cup holders.<a class="view-deal button" href="https://www.amazon.com/Lightweight-Leakproof-Insulated-Stainless-BPA-Free/dp/B0CHN7KDNZ" target="_blank" rel="nofollow" data-dimension112="731d8786-d14c-11f1-8eaf-793a3c91dbc4" data-action="Deal Block" data-label="IceFlow Cap and Carry Water Bottle (16 oz)" data-dimension48="IceFlow Cap and Carry Water Bottle (16 oz)" data-dimension25="$25">View Deal</a></p></div><div class="product"><a data-dimension112="f4cca750-d140-11f1-9c80-2f0de7014751" data-action="Deal Block" data-label="IceFlow 2.0 Flip Straw Tumbler (30 oz)" data-dimension48="IceFlow 2.0 Flip Straw Tumbler (30 oz)" data-dimension25="$26" href="https://www.amazon.com/STANLEY-Champagne-Resistant-Insulated-Stainless/dp/B0H48S2D7V" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:487px;"><p class="vanilla-image-block" style="padding-top:299.59%;"><img id="jfyqVfb82F2gre6soyu7ab" name="IceFlow 2.0 Flip Straw Tumbler (30 oz)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jfyqVfb82F2gre6soyu7ab-1920-80.jpg" mos="" align="middle" fullscreen="" width="487" height="1459" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/STANLEY-Champagne-Resistant-Insulated-Stainless/dp/B0H48S2D7V" target="_blank" rel="nofollow" data-dimension112="f4cca750-d140-11f1-9c80-2f0de7014751" data-action="Deal Block" data-label="IceFlow 2.0 Flip Straw Tumbler (30 oz)" data-dimension48="IceFlow 2.0 Flip Straw Tumbler (30 oz)" data-dimension25="$26">IceFlow 2.0 Flip Straw Tumbler (30 oz): was $35 now $26</a></strong><br />This Stanley features a 30oz capacity, a handle for transportation and a flip straw for easy sipping. The insulation can keep your drinks icy for up to 2 days.<a class="view-deal button" href="https://www.amazon.com/STANLEY-Champagne-Resistant-Insulated-Stainless/dp/B0H48S2D7V" target="_blank" rel="nofollow" data-dimension112="f4cca750-d140-11f1-9c80-2f0de7014751" data-action="Deal Block" data-label="IceFlow 2.0 Flip Straw Tumbler (30 oz)" data-dimension48="IceFlow 2.0 Flip Straw Tumbler (30 oz)" data-dimension25="$26">View Deal</a></p></div><div class="product"><a data-dimension112="f4cca7aa-d140-11f1-aabd-63c300e2883a" data-action="Deal Block" data-label="Classic Legendary Vacuum Bottle" data-dimension48="Classic Legendary Vacuum Bottle" data-dimension25="$29" href="https://www.amazon.com/Legendary-Leakproof-Insulated-Stainless-Hammertone/dp/B0BRKQDYTV" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:486px;"><p class="vanilla-image-block" style="padding-top:308.64%;"><img id="PRUhUxKXFDy7LbPYyKEiDi" name="Classic Legendary Vacuum Bottle" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/PRUhUxKXFDy7LbPYyKEiDi-1920-80.jpg" mos="" align="middle" fullscreen="" width="486" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Legendary-Leakproof-Insulated-Stainless-Hammertone/dp/B0BRKQDYTV" target="_blank" rel="nofollow" data-dimension112="f4cca7aa-d140-11f1-aabd-63c300e2883a" data-action="Deal Block" data-label="Classic Legendary Vacuum Bottle" data-dimension48="Classic Legendary Vacuum Bottle" data-dimension25="$29">Classic Legendary Vacuum Bottle: was $45 now $29</a></strong><br />Don't miss your chance to grab this Stanley deal — it's called a classic for a reason. Perfect for coffee, tea and even soup, this vacuum bottle comes with a mug for easy serving.<a class="view-deal button" href="https://www.amazon.com/Legendary-Leakproof-Insulated-Stainless-Hammertone/dp/B0BRKQDYTV" target="_blank" rel="nofollow" data-dimension112="f4cca7aa-d140-11f1-aabd-63c300e2883a" data-action="Deal Block" data-label="Classic Legendary Vacuum Bottle" data-dimension48="Classic Legendary Vacuum Bottle" data-dimension25="$29">View Deal</a></p></div><div class="product"><a data-dimension112="f4cca872-d140-11f1-9ea2-a3c63f11dc1a" data-action="Deal Block" data-label="IceFlow Fast Flow Water Bottle (24 oz)" data-dimension48="IceFlow Fast Flow Water Bottle (24 oz)" data-dimension25="$32" href="https://www.amazon.com/Lightweight-Leakproof-Insulated-Stainless-BPA-Free/dp/B0CFNRCVF8" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:316px;"><p class="vanilla-image-block" style="padding-top:278.16%;"><img id="ssCbmwVVnEcqjXw7DyC8F" name="Stanley Fast Flow.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ssCbmwVVnEcqjXw7DyC8F-1920-80.jpg" mos="" align="middle" fullscreen="" width="316" height="879" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Lightweight-Leakproof-Insulated-Stainless-BPA-Free/dp/B0CFNRCVF8" target="_blank" rel="nofollow" data-dimension112="f4cca872-d140-11f1-9ea2-a3c63f11dc1a" data-action="Deal Block" data-label="IceFlow Fast Flow Water Bottle (24 oz)" data-dimension48="IceFlow Fast Flow Water Bottle (24 oz)" data-dimension25="$32">IceFlow Fast Flow Water Bottle (24 oz): was $35 now $32</a></strong><br />This lightweight water bottle was designed to carry the most amount of water without weighing you down. Perfect for sipping during workouts, on your daily commute and camping trips, the bottle has a wide mouth opening that allows you to quench your thirst quickly. It's available in a variety of vibrant hues and four different sizes. <a class="view-deal button" href="https://www.amazon.com/Lightweight-Leakproof-Insulated-Stainless-BPA-Free/dp/B0CFNRCVF8" target="_blank" rel="nofollow" data-dimension112="f4cca872-d140-11f1-9ea2-a3c63f11dc1a" data-action="Deal Block" data-label="IceFlow Fast Flow Water Bottle (24 oz)" data-dimension48="IceFlow Fast Flow Water Bottle (24 oz)" data-dimension25="$32">View Deal</a></p></div><div class="product"><a data-dimension112="f4cca8d6-d140-11f1-8a3f-8761188c4a86" data-action="Deal Block" data-label="Quencher ProTour Flipstraw Tumbler (40 oz)" data-dimension48="Quencher ProTour Flipstraw Tumbler (40 oz)" data-dimension25="$33" href="https://www.amazon.com/STANLEY-Leakproof-Cupholder-Compatible-Insulated/dp/B0G77P82ZT" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:784px;"><p class="vanilla-image-block" style="padding-top:186.10%;"><img id="8KeoEbWJrTGTCHq4axhjtL" name="Quencher ProTour Flipstraw Tumbler (40 oz)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/8KeoEbWJrTGTCHq4axhjtL-1920-80.jpg" mos="" align="middle" fullscreen="" width="784" height="1459" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/STANLEY-Leakproof-Cupholder-Compatible-Insulated/dp/B0G77P82ZT" target="_blank" rel="nofollow" data-dimension112="f4cca8d6-d140-11f1-8a3f-8761188c4a86" data-action="Deal Block" data-label="Quencher ProTour Flipstraw Tumbler (40 oz)" data-dimension48="Quencher ProTour Flipstraw Tumbler (40 oz)" data-dimension25="$33">Quencher ProTour Flipstraw Tumbler (40 oz): was $45 now $33</a></strong><br />This Stanley tumbler lets you sip without worry thanks to its flip straw lid. All you have to do is flip up the built-in straw for a quick drink, then snap it shut to prevent any spills. Designed to fit in a car cup holder, you'll be able to take it with you on all adventures and it can keep your drinks hot or cold for hours thanks to its double walled insulation.<a class="view-deal button" href="https://www.amazon.com/STANLEY-Leakproof-Cupholder-Compatible-Insulated/dp/B0G77P82ZT" target="_blank" rel="nofollow" data-dimension112="f4cca8d6-d140-11f1-8a3f-8761188c4a86" data-action="Deal Block" data-label="Quencher ProTour Flipstraw Tumbler (40 oz)" data-dimension48="Quencher ProTour Flipstraw Tumbler (40 oz)" data-dimension25="$33">View Deal</a></p></div><div class="product"><a data-dimension112="f4cca93a-d140-11f1-96f4-f1b1cbee777c" data-action="Deal Block" data-label="Quencher H2.0 Tumbler (40 oz)" data-dimension48="Quencher H2.0 Tumbler (40 oz)" data-dimension25="$34" href="https://www.amazon.com/STANLEY-Flowstate-3-Position-Compatible-Insulated/dp/B0CP9Y2SKW" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:400px;"><p class="vanilla-image-block" style="padding-top:219.75%;"><img id="ho8fBjchigjZLwpGRcTDCn" name="Stanley sage" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ho8fBjchigjZLwpGRcTDCn-1920-80.jpg" mos="" align="middle" fullscreen="" width="400" height="879" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/STANLEY-Flowstate-3-Position-Compatible-Insulated/dp/B0CP9Y2SKW" target="_blank" rel="nofollow" data-dimension112="f4cca93a-d140-11f1-96f4-f1b1cbee777c" data-action="Deal Block" data-label="Quencher H2.0 Tumbler (40 oz)" data-dimension48="Quencher H2.0 Tumbler (40 oz)" data-dimension25="$34">Quencher H2.0 Tumbler (40 oz): was $45 now $34</a></strong><br />Looking for something large to hold your beverages? The popular 40-ounce Stanley Quencher H2.0 Tumbler fits into most car cup holders. It's made with recycled stainless steel, features a 3-position lid, and reusable straw. Its double-wall vacuum insulation can keep water ice cold for 40 hours. <a class="view-deal button" href="https://www.amazon.com/STANLEY-Flowstate-3-Position-Compatible-Insulated/dp/B0CP9Y2SKW" target="_blank" rel="nofollow" data-dimension112="f4cca93a-d140-11f1-96f4-f1b1cbee777c" data-action="Deal Block" data-label="Quencher H2.0 Tumbler (40 oz)" data-dimension48="Quencher H2.0 Tumbler (40 oz)" data-dimension25="$34">View Deal</a></p></div><div class="product"><a data-dimension112="f4cca99e-d140-11f1-b20d-b50ed10b632e" data-action="Deal Block" data-label="IceFlow Flip Straw 2.0 Water Bottle (36 oz)" data-dimension48="IceFlow Flip Straw 2.0 Water Bottle (36 oz)" data-dimension25="$42" href="https://www.amazon.com/Lightweight-Leak-Resistant-Insulated-Stainless-BPA-Free/dp/B0CYVRB35T" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:493px;"><p class="vanilla-image-block" style="padding-top:304.26%;"><img id="srCGwMucdiuWiGjkM6xtK4" name="51Y0idpsdWL._AC_SL1500_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/srCGwMucdiuWiGjkM6xtK4-1920-80.jpg" mos="" align="middle" fullscreen="" width="493" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Lightweight-Leak-Resistant-Insulated-Stainless-BPA-Free/dp/B0CYVRB35T" target="_blank" rel="nofollow" data-dimension112="f4cca99e-d140-11f1-b20d-b50ed10b632e" data-action="Deal Block" data-label="IceFlow Flip Straw 2.0 Water Bottle (36 oz)" data-dimension48="IceFlow Flip Straw 2.0 Water Bottle (36 oz)" data-dimension25="$42">IceFlow Flip Straw 2.0 Water Bottle (36 oz): was $45 now $42</a></strong><br />Made with AeroLight spun steel, Stanley bills the IceFlow Flip Straw 2.0 Water Bottle as being 33% lighter than other stainless steel water bottles. That makes it super easy to take around with you, and the Flip Straw lid makes it super easy to sip from too.<a class="view-deal button" href="https://www.amazon.com/Lightweight-Leak-Resistant-Insulated-Stainless-BPA-Free/dp/B0CYVRB35T" target="_blank" rel="nofollow" data-dimension112="f4cca99e-d140-11f1-b20d-b50ed10b632e" data-action="Deal Block" data-label="IceFlow Flip Straw 2.0 Water Bottle (36 oz)" data-dimension48="IceFlow Flip Straw 2.0 Water Bottle (36 oz)" data-dimension25="$42">View Deal</a></p></div><div class="product"><a data-dimension112="f4ccaa0c-d140-11f1-b398-8333244e253c" data-action="Deal Block" data-label="IceFlow Flip Straw Jug with Handle (40 oz)" data-dimension48="IceFlow Flip Straw Jug with Handle (40 oz)" data-dimension25="$57" href="https://www.amazon.com/Stanley-IceFlow-Stainless-Steel-Tumbler/dp/B0CT4BJ4Q1" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:702px;"><p class="vanilla-image-block" style="padding-top:213.68%;"><img id="yYqTMUAPSrnqJ4EKwXCMLC" name="61MXE5ctmHL._AC_SL1500_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/yYqTMUAPSrnqJ4EKwXCMLC-1920-80.jpg" mos="" align="middle" fullscreen="" width="702" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Stanley-IceFlow-Stainless-Steel-Tumbler/dp/B0CT4BJ4Q1" target="_blank" rel="nofollow" data-dimension112="f4ccaa0c-d140-11f1-b398-8333244e253c" data-action="Deal Block" data-label="IceFlow Flip Straw Jug with Handle (40 oz)" data-dimension48="IceFlow Flip Straw Jug with Handle (40 oz)" data-dimension25="$57">IceFlow Flip Straw Jug with Handle (40 oz): was $69 now $57</a></strong><br />While this water jug is the smallest of its family from Stanley, it still houses an impressive 40 oz of water. It'll keep your cold drinks cold for up to 14 hours, while having a sweat-proof coating that's perfect for trips to the gym. And when you're done drinking, just pop it in the dishwasher to clean.<a class="view-deal button" href="https://www.amazon.com/Stanley-IceFlow-Stainless-Steel-Tumbler/dp/B0CT4BJ4Q1" target="_blank" rel="nofollow" data-dimension112="f4ccaa0c-d140-11f1-b398-8333244e253c" data-action="Deal Block" data-label="IceFlow Flip Straw Jug with Handle (40 oz)" data-dimension48="IceFlow Flip Straw Jug with Handle (40 oz)" data-dimension25="$57">View Deal</a></p></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 21 walking shoe deals with up to 61% off: best fall sales on Skechers, Birkenstocks and New Balance ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Fall is well and truly here. But that doesn't mean you have to hole up inside for the rest of the year. To keep enjoying the great outdoors, there are a bunch of deals you can grab on walking shoes from Skechers, Birkenstocks and more.</p><p>Over at <a href="https://www.amazon.com/b?node=211953829011" target="_blank" rel="nofollow">Amazon you'll find discounts on everything from Skechers slip-ins to Dr. Martens boots</a>. So if you need a new pair, I'm sharing the best savings below!</p><p><strong>Note: </strong>prices can vary depending on the size and color you select. To find the best deals, check out the different colors available in your size.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links </span></h3><ul><li><strong>Asics: </strong><a href="https://www.asics.com/us/en-us/clearance/c/aa60000000/?" target="_blank" rel="nofollow"><strong>deals from $49</strong></a></li><li><strong>Brooks: </strong><a href="https://www.amazon.com/stores/Brooks/page/B6834DFA-396F-4E38-98F6-3D2739393271?" target="_blank" rel="nofollow"><strong>up to 40% off</strong></a></li><li><strong>Hoka: </strong><a href="https://www.hoka.com/en/us/sale/" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li><li><strong>Nike: </strong><a href="https://www.nike.com/w/mens-shoes-nik1zy7ok" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li><li><strong>New Balance: </strong><a href="https://www.amazon.com/stores/NewBalanceAthleticShoeInc/page/855D4CDF-ADB7-4BE8-9E26-A085D029E4B5" target="_blank" rel="nofollow"><strong>deals from $39</strong></a></li><li><strong>Skechers: </strong><a href="https://www.skechers.com/women/shop-by-activity/walking/" target="_blank" rel="nofollow"><strong>20% off for members</strong></a></li></ul><h3 class="article-body__section" id="section-skechers"><span>Skechers</span></h3><div class="product"><a data-dimension112="2c3abf7c-d12f-11f1-b55a-c77191e28df0" data-action="Deal Block" data-label="Hands Free Slip-in Ultra Flex 3.0 - Brilliant Path Sneakers (Women's)" data-dimension48="Hands Free Slip-in Ultra Flex 3.0 - Brilliant Path Sneakers (Women's)" data-dimension25="$37" href="https://www.amazon.com/Skechers-Womens-BrilliantPath-Sneaker-Periwinkle/dp/B0CB1TB6FF" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:64.60%;"><img id="ktgq75pP2AA2yCeBTtmCNi" name="Hands Free Slip-in Ultra Flex 3.0 - Brilliant Path Sneakers (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ktgq75pP2AA2yCeBTtmCNi-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="449" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-BrilliantPath-Sneaker-Periwinkle/dp/B0CB1TB6FF" target="_blank" rel="nofollow" data-dimension112="2c3abf7c-d12f-11f1-b55a-c77191e28df0" data-action="Deal Block" data-label="Hands Free Slip-in Ultra Flex 3.0 - Brilliant Path Sneakers (Women's)" data-dimension48="Hands Free Slip-in Ultra Flex 3.0 - Brilliant Path Sneakers (Women's)" data-dimension25="$37">Hands Free Slip-in Ultra Flex 3.0 - Brilliant Path Sneakers (Women's): was $39 now $37</a></strong><br />The Skechers Ultra Flex 3.0 Brilliant Path slip-ons are our choice for the most versatile Skechers sneaker. As you'd expect, they're lightweight and comfortable with pillowy soft midsoles and Air-Cooled Memory Foam. In our <a href="https://www.tomsguide.com/reviews/Skechers-Slip-Ins-Ultra-Flex-3.0">Skechers Hands Free Ultra Flex 3.0 Brilliant Path review</a> we determined that they're great for casual wear, but we don't recommend them for high-impact exercise.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-BrilliantPath-Sneaker-Periwinkle/dp/B0CB1TB6FF" target="_blank" rel="nofollow" data-dimension112="2c3abf7c-d12f-11f1-b55a-c77191e28df0" data-action="Deal Block" data-label="Hands Free Slip-in Ultra Flex 3.0 - Brilliant Path Sneakers (Women's)" data-dimension48="Hands Free Slip-in Ultra Flex 3.0 - Brilliant Path Sneakers (Women's)" data-dimension25="$37">View Deal</a></p></div><div class="product"><a data-dimension112="2c3ac012-d12f-11f1-b9d7-d9a0451e464c" data-action="Deal Block" data-label="Go Walk Joy Cushioning Sneakers (Women's)" data-dimension48="Go Walk Joy Cushioning Sneakers (Women's)" data-dimension25="$44" href="https://www.amazon.com/Skechers-Sneaker-5Gen-Cushioning-Air-Cooled-Breathable/dp/B072LFYC5Q" 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:65.54%;"><img id="sMKHY4Hdbe52xJSyHG6eJg" name="81t7vPwv8wL._AC_SX679_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sMKHY4Hdbe52xJSyHG6eJg-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="445" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Sneaker-5Gen-Cushioning-Air-Cooled-Breathable/dp/B072LFYC5Q" target="_blank" rel="nofollow" data-dimension112="2c3ac012-d12f-11f1-b9d7-d9a0451e464c" data-action="Deal Block" data-label="Go Walk Joy Cushioning Sneakers (Women's)" data-dimension48="Go Walk Joy Cushioning Sneakers (Women's)" data-dimension25="$44">Go Walk Joy Cushioning Sneakers (Women's): was $51 now $44</a></strong><br />These slip-in Skechers shoes have all of the cushioning and comfort you've come to know and love from the brand. There's also a breathable upper, to keep your feet cool and comfortable.<a class="view-deal button" href="https://www.amazon.com/Skechers-Sneaker-5Gen-Cushioning-Air-Cooled-Breathable/dp/B072LFYC5Q" target="_blank" rel="nofollow" data-dimension112="2c3ac012-d12f-11f1-b9d7-d9a0451e464c" data-action="Deal Block" data-label="Go Walk Joy Cushioning Sneakers (Women's)" data-dimension48="Go Walk Joy Cushioning Sneakers (Women's)" data-dimension25="$44">View Deal</a></p></div><div class="product"><a data-dimension112="2c3ac076-d12f-11f1-9225-cdf77c0e89ee" data-action="Deal Block" data-label="Respected-Holmgren Slip-in Loafer (Men's)" data-dimension48="Respected-Holmgren Slip-in Loafer (Men's)" data-dimension25="$60" href="https://www.amazon.com/Skechers-Respected-Holmgren-Slip-Loafer-Charcoal/dp/B0BYBFZXL8" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1137px;"><p class="vanilla-image-block" style="padding-top:61.13%;"><img id="p79NadjFtsEoazJoKeBmgR" name="Respected-Holmgren Slip-in Loafer (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/p79NadjFtsEoazJoKeBmgR-1920-80.jpg" mos="" align="middle" fullscreen="" width="1137" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Respected-Holmgren-Slip-Loafer-Charcoal/dp/B0BYBFZXL8" target="_blank" rel="nofollow" data-dimension112="2c3ac076-d12f-11f1-9225-cdf77c0e89ee" data-action="Deal Block" data-label="Respected-Holmgren Slip-in Loafer (Men's)" data-dimension48="Respected-Holmgren Slip-in Loafer (Men's)" data-dimension25="$60">Respected-Holmgren Slip-in Loafer (Men's): was $89 now $60</a></strong><br />The simple but stylish design of the Respected-Holmgren Slip-in Loafer makes them a great pick for any activity. The Air Cooled Memory Foam delivers breathable comfort, and the Goodyear rubber outsole provides reliable grip in wet or icy conditions.<a class="view-deal button" href="https://www.amazon.com/Skechers-Respected-Holmgren-Slip-Loafer-Charcoal/dp/B0BYBFZXL8" target="_blank" rel="nofollow" data-dimension112="2c3ac076-d12f-11f1-9225-cdf77c0e89ee" data-action="Deal Block" data-label="Respected-Holmgren Slip-in Loafer (Men's)" data-dimension48="Respected-Holmgren Slip-in Loafer (Men's)" data-dimension25="$60">View Deal</a></p></div><div class="product"><a data-dimension112="558f67c2-d131-11f1-8c70-6fe2d258a912" data-action="Deal Block" data-label="Arch Fit 2.0 - Star Bound" data-dimension48="Arch Fit 2.0 - Star Bound" data-dimension25="$94" href="https://www.amazon.com/Skechers-Womens-Sneaker-White-7/dp/B0CPJFGK3G/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:819px;"><p class="vanilla-image-block" style="padding-top:84.86%;"><img id="VJnWP38VkGWMuARJrWadJB" name="Skechers Arch Fit 2.0 - Star Bound" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/VJnWP38VkGWMuARJrWadJB-1920-80.jpg" mos="" align="middle" fullscreen="" width="819" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Sneaker-White-7/dp/B0CPJFGK3G/" target="_blank" rel="nofollow" data-dimension112="558f67c2-d131-11f1-8c70-6fe2d258a912" data-action="Deal Block" data-label="Arch Fit 2.0 - Star Bound" data-dimension48="Arch Fit 2.0 - Star Bound" data-dimension25="$94">Arch Fit 2.0 - Star Bound: was $102 now $94</a></strong><br />The <a href="https://www.tomsguide.com/wellness/fitness/skechers-arch-fit-2-0-star-bound-review">Skechers Arch Fit 2.0 Star Bound</a> sneakers offer comfort and support for anyone looking for a versatile option to wear to run errands all day. The Air Cooled Memory Foam and Arch Fit technology work together to provide a bouncy walking experience, and the elevated heel aids in maintaining good posture by promoting heel-to-toe steps. The leather of the upper takes a little time to bend with your footsteps, but once it does, you will reach for them every day.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Sneaker-White-7/dp/B0CPJFGK3G/" target="_blank" rel="nofollow" data-dimension112="558f67c2-d131-11f1-8c70-6fe2d258a912" data-action="Deal Block" data-label="Arch Fit 2.0 - Star Bound" data-dimension48="Arch Fit 2.0 - Star Bound" data-dimension25="$94">View Deal</a></p></div><h3 class="article-body__section" id="section-birkenstocks"><span>Birkenstocks</span></h3><div class="product"><a data-dimension112="2c3ac134-d12f-11f1-9174-094bd5538ab4" data-action="Deal Block" data-label="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension48="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension25="$30" href="https://www.nordstromrack.com/s/birkenstock-arizona-stealth-buckle-eva-slide-sandal-women/7945865?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1560px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="3Qt2UrH7ESWm55JQpi8aXQ" name="Arizona Stealth" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3Qt2UrH7ESWm55JQpi8aXQ-1920-80.jpg" mos="" align="middle" fullscreen="" width="1560" height="2340" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nordstromrack.com/s/birkenstock-arizona-stealth-buckle-eva-slide-sandal-women/7945865?" target="_blank" rel="nofollow" data-dimension112="2c3ac134-d12f-11f1-9174-094bd5538ab4" data-action="Deal Block" data-label="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension48="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension25="$30">Arizona Stealth Buckle EVA Slide (Women's): was $54 now $30</a></strong><br />A pair of Birkenstocks for $30??? Sign me up. These waterproof slides are perfect for hanging out indoors, or going to the beach or pool. They feature a rubber-like texture with sleek adjustable straps and a grippy traction sole. <a class="view-deal button" href="https://www.nordstromrack.com/s/birkenstock-arizona-stealth-buckle-eva-slide-sandal-women/7945865?" target="_blank" rel="nofollow" data-dimension112="2c3ac134-d12f-11f1-9174-094bd5538ab4" data-action="Deal Block" data-label="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension48="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension25="$30">View Deal</a></p></div><div class="product"><a data-dimension112="508c7720-d130-11f1-aa16-1d13b2533b71" data-action="Deal Block" data-label="Lutry 365 Clog - Suede (Women's)" data-dimension48="Lutry 365 Clog - Suede (Women's)" data-dimension25="$61" href="https://www.amazon.com/Birkenstock-Womens-Lutry-365-Suede-Narrow/dp/B0FH15W1SY" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:46.62%;"><img id="b4FtpSQLYePgojSeRWMMh8" name="Lutry 365 Clog - Suede (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/b4FtpSQLYePgojSeRWMMh8-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="324" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Birkenstock-Womens-Lutry-365-Suede-Narrow/dp/B0FH15W1SY" target="_blank" rel="nofollow" data-dimension112="508c7720-d130-11f1-aa16-1d13b2533b71" data-action="Deal Block" data-label="Lutry 365 Clog - Suede (Women's)" data-dimension48="Lutry 365 Clog - Suede (Women's)" data-dimension25="$61">Lutry 365 Clog - Suede (Women's): was $154 now $61</a></strong><br />You don't see a Birkenstock discount this big every day, so grab it while you can if it's available in your size! These slip-on clogs have a premium suede upper, making them look and feel super luxurious.<a class="view-deal button" href="https://www.amazon.com/Birkenstock-Womens-Lutry-365-Suede-Narrow/dp/B0FH15W1SY" target="_blank" rel="nofollow" data-dimension112="508c7720-d130-11f1-aa16-1d13b2533b71" data-action="Deal Block" data-label="Lutry 365 Clog - Suede (Women's)" data-dimension48="Lutry 365 Clog - Suede (Women's)" data-dimension25="$61">View Deal</a></p></div><div class="product"><a data-dimension112="2c3ac1b6-d12f-11f1-b4df-f9cca801955f" data-action="Deal Block" data-label="Papilio Florida Platform Flex (Women's)" data-dimension48="Papilio Florida Platform Flex (Women's)" data-dimension25="$74" href="https://www.nordstromrack.com/s/florida-flex-platform-slide-sandal-women/7953334?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1560px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="YToScW8bDWGEAAJqToJey" name="florida" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/YToScW8bDWGEAAJqToJey-1920-80.jpg" mos="" align="middle" fullscreen="" width="1560" height="2340" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nordstromrack.com/s/florida-flex-platform-slide-sandal-women/7953334?" target="_blank" rel="nofollow" data-dimension112="2c3ac1b6-d12f-11f1-b4df-f9cca801955f" data-action="Deal Block" data-label="Papilio Florida Platform Flex (Women's)" data-dimension48="Papilio Florida Platform Flex (Women's)" data-dimension25="$74">Papilio Florida Platform Flex (Women's): was $144 now $74</a></strong><br />These Papilio by Birkenstock sandals feature a platform and three straps for extra support. Reviewers love their iconic design and comfortable, adjustable fit.<a class="view-deal button" href="https://www.nordstromrack.com/s/florida-flex-platform-slide-sandal-women/7953334?" target="_blank" rel="nofollow" data-dimension112="2c3ac1b6-d12f-11f1-b4df-f9cca801955f" data-action="Deal Block" data-label="Papilio Florida Platform Flex (Women's)" data-dimension48="Papilio Florida Platform Flex (Women's)" data-dimension25="$74">View Deal</a></p></div><h3 class="article-body__section" id="section-vans"><span>Vans</span></h3><div class="product"><a data-dimension112="508c7bc6-d130-11f1-b083-a1a8585d05a8" data-action="Deal Block" data-label="Asher Adult Low Top Sneakers (Women's)" data-dimension48="Asher Adult Low Top Sneakers (Women's)" data-dimension25="$39" href="https://www.amazon.com/Vans-Comfortable-Sneakers-Walking-Everyday/dp/B0FL84PVY7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1047px;"><p class="vanilla-image-block" style="padding-top:66.38%;"><img id="QKub3ycPjdDp9fUWpA3uZc" name="Asher Adult Low Top Sneakers (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/QKub3ycPjdDp9fUWpA3uZc-1920-80.jpg" mos="" align="middle" fullscreen="" width="1047" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Vans-Comfortable-Sneakers-Walking-Everyday/dp/B0FL84PVY7" target="_blank" rel="nofollow" data-dimension112="508c7bc6-d130-11f1-b083-a1a8585d05a8" data-action="Deal Block" data-label="Asher Adult Low Top Sneakers (Women's)" data-dimension48="Asher Adult Low Top Sneakers (Women's)" data-dimension25="$39">Asher Adult Low Top Sneakers (Women's): was $55 now $39</a></strong><br />Vans' low-top slip-on shoes are a steal starting from just $39! The simple design means they couldn't be any more versatile and easy to style — and the color selection is great, too. <a class="view-deal button" href="https://www.amazon.com/Vans-Comfortable-Sneakers-Walking-Everyday/dp/B0FL84PVY7" target="_blank" rel="nofollow" data-dimension112="508c7bc6-d130-11f1-b083-a1a8585d05a8" data-action="Deal Block" data-label="Asher Adult Low Top Sneakers (Women's)" data-dimension48="Asher Adult Low Top Sneakers (Women's)" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="508c7c84-d130-11f1-8116-bb3e84775756" data-action="Deal Block" data-label="Brooklyn LS Shoe (Women's)" data-dimension48="Brooklyn LS Shoe (Women's)" data-dimension25="$52" href="https://www.amazon.com/Vans-Brooklyn-Low-Top-Sneakers-Everyday/dp/B0D7QCNLHJ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1005px;"><p class="vanilla-image-block" style="padding-top:69.15%;"><img id="rJDozMtKWunUE3PrvRZ9kQ" name="Brooklyn LS Shoe (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/rJDozMtKWunUE3PrvRZ9kQ-1920-80.jpg" mos="" align="middle" fullscreen="" width="1005" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Vans-Brooklyn-Low-Top-Sneakers-Everyday/dp/B0D7QCNLHJ" target="_blank" rel="nofollow" data-dimension112="508c7c84-d130-11f1-8116-bb3e84775756" data-action="Deal Block" data-label="Brooklyn LS Shoe (Women's)" data-dimension48="Brooklyn LS Shoe (Women's)" data-dimension25="$52">Brooklyn LS Shoe (Women's): was $70 now $52</a></strong><br />These classic Vans can be yours starting from just $52 right now. Their padded collar makes them comfortable to wear, and they feature the iconic Vans stripe down the side.<a class="view-deal button" href="https://www.amazon.com/Vans-Brooklyn-Low-Top-Sneakers-Everyday/dp/B0D7QCNLHJ" target="_blank" rel="nofollow" data-dimension112="508c7c84-d130-11f1-8116-bb3e84775756" data-action="Deal Block" data-label="Brooklyn LS Shoe (Women's)" data-dimension48="Brooklyn LS Shoe (Women's)" data-dimension25="$52">View Deal</a></p></div><h3 class="article-body__section" id="section-cushionaire"><span>Cushionaire</span></h3><div class="product"><a data-dimension112="2c3ac3fa-d12f-11f1-9469-391b5c391713" data-action="Deal Block" data-label="Laz Cork Footbed Sandals" data-dimension48="Laz Cork Footbed Sandals" data-dimension25="$39" href="https://www.amazon.com/dp/B0H8FB19F7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:606px;"><p class="vanilla-image-block" style="padding-top:114.69%;"><img id="GknzxZr7RhbEEsFqQG3HjN" name="Laz" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/GknzxZr7RhbEEsFqQG3HjN-1920-80.jpg" mos="" align="middle" fullscreen="" width="606" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0H8FB19F7" target="_blank" rel="nofollow" data-dimension112="2c3ac3fa-d12f-11f1-9469-391b5c391713" data-action="Deal Block" data-label="Laz Cork Footbed Sandals" data-dimension48="Laz Cork Footbed Sandals" data-dimension25="$39">Laz Cork Footbed Sandals: was $59 now $39</a></strong><br />If you're in the market for some Birkenstocks but don't want to pay the hefty price, these Cushionaire sandals are the next best thing. Crafted from high-quality faux leather, the sandals feature a soft lining and adjustable double buckle strap. They're also available in a plethora of colors, although price may vary. <a class="view-deal button" href="https://www.amazon.com/dp/B0H8FB19F7" target="_blank" rel="nofollow" data-dimension112="2c3ac3fa-d12f-11f1-9469-391b5c391713" data-action="Deal Block" data-label="Laz Cork Footbed Sandals" data-dimension48="Laz Cork Footbed Sandals" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="2c3ac45e-d12f-11f1-a100-c3e3fffc96dc" data-action="Deal Block" data-label="Lens Sandals" data-dimension48="Lens Sandals" data-dimension25="$49" href="https://www.amazon.com/dp/B0GZJ8VB6M" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:543px;"><p class="vanilla-image-block" style="padding-top:127.99%;"><img id="v9a622fikJvyBJaGFHRcpH" name="Cushionaire Lens" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/v9a622fikJvyBJaGFHRcpH-1920-80.jpg" mos="" align="middle" fullscreen="" width="543" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0GZJ8VB6M" target="_blank" rel="nofollow" data-dimension112="2c3ac45e-d12f-11f1-a100-c3e3fffc96dc" data-action="Deal Block" data-label="Lens Sandals" data-dimension48="Lens Sandals" data-dimension25="$49">Lens Sandals: was $69 now $49</a></strong><br />Looking for a fun little twist on a classic slide? Slip into these comfortable sandals that feature unique braided straps. They have a cushioned footbed and a contoured sole making them extra comfy. They also pair nicely with dresses, denim and casual outfits.<a class="view-deal button" href="https://www.amazon.com/dp/B0GZJ8VB6M" target="_blank" rel="nofollow" data-dimension112="2c3ac45e-d12f-11f1-a100-c3e3fffc96dc" data-action="Deal Block" data-label="Lens Sandals" data-dimension48="Lens Sandals" data-dimension25="$49">View Deal</a></p></div><h3 class="article-body__section" id="section-nortiv-8"><span>Nortiv 8</span></h3><div class="product"><a data-dimension112="2c3ac512-d12f-11f1-b603-b1ccc341b16a" data-action="Deal Block" data-label="Lightweight Ankle Hiking Boots (Women's)" data-dimension48="Lightweight Ankle Hiking Boots (Women's)" data-dimension25="$39" href="https://www.amazon.com/dp/B0BFPR8Y2Y" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:873px;"><p class="vanilla-image-block" style="padding-top:79.61%;"><img id="5QdW6J7JmJEfcovDJA6ZgM" name="Lightweight Ankle Hiking Boots (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/5QdW6J7JmJEfcovDJA6ZgM-1920-80.jpg" mos="" align="middle" fullscreen="" width="873" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0BFPR8Y2Y" target="_blank" rel="nofollow" data-dimension112="2c3ac512-d12f-11f1-b603-b1ccc341b16a" data-action="Deal Block" data-label="Lightweight Ankle Hiking Boots (Women's)" data-dimension48="Lightweight Ankle Hiking Boots (Women's)" data-dimension25="$39">Lightweight Ankle Hiking Boots (Women's): was $47 now $39</a></strong><br />Nortiv 8's budget-friendly hiking boots just got a discount, making them even better value. They're built to be lightweight, comfortable and durable, with grip to stop you from slipping on the trails.<a class="view-deal button" href="https://www.amazon.com/dp/B0BFPR8Y2Y" target="_blank" rel="nofollow" data-dimension112="2c3ac512-d12f-11f1-b603-b1ccc341b16a" data-action="Deal Block" data-label="Lightweight Ankle Hiking Boots (Women's)" data-dimension48="Lightweight Ankle Hiking Boots (Women's)" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="2c3ac56c-d12f-11f1-b6ca-9fc55314d528" data-action="Deal Block" data-label="Trail Running Walking Shoes (Men's)" data-dimension48="Trail Running Walking Shoes (Men's)" data-dimension25="$56" href="https://www.amazon.com/dp/B0H7BRYLZ1" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1093px;"><p class="vanilla-image-block" style="padding-top:63.59%;"><img id="98qPHFxV2Ykz8EZjKZouLY" name="Trail Running Walking Shoes (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/98qPHFxV2Ykz8EZjKZouLY-1920-80.jpg" mos="" align="middle" fullscreen="" width="1093" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0H7BRYLZ1" target="_blank" rel="nofollow" data-dimension112="2c3ac56c-d12f-11f1-b6ca-9fc55314d528" data-action="Deal Block" data-label="Trail Running Walking Shoes (Men's)" data-dimension48="Trail Running Walking Shoes (Men's)" data-dimension25="$56">Trail Running Walking Shoes (Men's): was $69 now $56</a></strong><br />These Nortiv 8 shoes come in handy for both hiking and trail runs. They're lightweight, packed with cushioning and have grip to keep you steady. Plus, with this discount, they're affordable too.<a class="view-deal button" href="https://www.amazon.com/dp/B0H7BRYLZ1" target="_blank" rel="nofollow" data-dimension112="2c3ac56c-d12f-11f1-b6ca-9fc55314d528" data-action="Deal Block" data-label="Trail Running Walking Shoes (Men's)" data-dimension48="Trail Running Walking Shoes (Men's)" data-dimension25="$56">View Deal</a></p></div><h3 class="article-body__section" id="section-new-balance"><span>New Balance</span></h3><div class="product"><a data-dimension112="2c3ac62a-d12f-11f1-8a8b-77e3e9abadb3" data-action="Deal Block" data-label="237 V1 Sneaker (Men's)" data-dimension48="237 V1 Sneaker (Men's)" data-dimension25="$69" href="https://www.amazon.com/New-Balance-Sneaker-White-Brighton/dp/B0F4MB4R6V" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1290px;"><p class="vanilla-image-block" style="padding-top:50.47%;"><img id="sTxmZw69B2s8LpTEsCvTfT" name="237 V1 Sneaker (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sTxmZw69B2s8LpTEsCvTfT-1920-80.jpg" mos="" align="middle" fullscreen="" width="1290" height="651" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-Sneaker-White-Brighton/dp/B0F4MB4R6V" target="_blank" rel="nofollow" data-dimension112="2c3ac62a-d12f-11f1-8a8b-77e3e9abadb3" data-action="Deal Block" data-label="237 V1 Sneaker (Men's)" data-dimension48="237 V1 Sneaker (Men's)" data-dimension25="$69">237 V1 Sneaker (Men's): was $84 now $69</a></strong><br />Right now you can get the New Balance 237 V1 sneakers on sale and add a touch of style to your wardrobe. They have a suede and mesh upper with a sleek three-tone color scheme.<a class="view-deal button" href="https://www.amazon.com/New-Balance-Sneaker-White-Brighton/dp/B0F4MB4R6V" target="_blank" rel="nofollow" data-dimension112="2c3ac62a-d12f-11f1-8a8b-77e3e9abadb3" data-action="Deal Block" data-label="237 V1 Sneaker (Men's)" data-dimension48="237 V1 Sneaker (Men's)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="2c3ac684-d12f-11f1-a5d7-ff54bdfdf464" data-action="Deal Block" data-label="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension48="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension25="$98" href="https://www.amazon.com/New-Balance-FuelCell-Walking-Electric/dp/B0D2Y7L3DC" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:755px;"><p class="vanilla-image-block" style="padding-top:55.23%;"><img id="ufsfox6NerPUoEY6YYZYXk" name="FuelCell Walker Elite V1 Walking Shoe (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ufsfox6NerPUoEY6YYZYXk-1920-80.jpg" mos="" align="middle" fullscreen="" width="755" height="417" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-FuelCell-Walking-Electric/dp/B0D2Y7L3DC" target="_blank" rel="nofollow" data-dimension112="2c3ac684-d12f-11f1-a5d7-ff54bdfdf464" data-action="Deal Block" data-label="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension48="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension25="$98">FuelCell Walker Elite V1 Walking Shoe (Women's): was $139 now $98</a></strong><br />Engineered for walking, the New Balance FuelCell Walker Elite V1 Walking Shoes are cushioned, stable, and propel your feet forward with each step. They look super sleek, too. <a class="view-deal button" href="https://www.amazon.com/New-Balance-FuelCell-Walking-Electric/dp/B0D2Y7L3DC" target="_blank" rel="nofollow" data-dimension112="2c3ac684-d12f-11f1-a5d7-ff54bdfdf464" data-action="Deal Block" data-label="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension48="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension25="$98">View Deal</a></p></div><h3 class="article-body__section" id="section-dr-martens"><span>Dr Martens</span></h3><div class="product"><a data-dimension112="2c3ac7e2-d12f-11f1-9654-3b855454325c" data-action="Deal Block" data-label="Holly Leather Quad Shoe (Women's)" data-dimension48="Holly Leather Quad Shoe (Women's)" data-dimension25="$83" href="https://www.amazon.com/Dr-Martens-Holly-Buttero-Womens/dp/B07MHM313L" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:72.37%;"><img id="AgdKAuExiUftz8NTZy4PoQ" name="Holly Leather Quad Shoe (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/AgdKAuExiUftz8NTZy4PoQ-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="503" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Dr-Martens-Holly-Buttero-Womens/dp/B07MHM313L" target="_blank" rel="nofollow" data-dimension112="2c3ac7e2-d12f-11f1-9654-3b855454325c" data-action="Deal Block" data-label="Holly Leather Quad Shoe (Women's)" data-dimension48="Holly Leather Quad Shoe (Women's)" data-dimension25="$83">Holly Leather Quad Shoe (Women's): was $170 now $83</a></strong><br />Don't miss your chance to score this huge saving — it's not going to be available for long. These Dr Martens shoes have 1.5-inch soles and a pretty ribbon at the front! Perfect to add some "dark academia" vibes to your fall outfits.<a class="view-deal button" href="https://www.amazon.com/Dr-Martens-Holly-Buttero-Womens/dp/B07MHM313L" target="_blank" rel="nofollow" data-dimension112="2c3ac7e2-d12f-11f1-9654-3b855454325c" data-action="Deal Block" data-label="Holly Leather Quad Shoe (Women's)" data-dimension48="Holly Leather Quad Shoe (Women's)" data-dimension25="$83">View Deal</a></p></div><div class="product"><a data-dimension112="2c3ac850-d12f-11f1-a753-47a3eccd64c4" data-action="Deal Block" data-label="1460 8 Eye Boot (Unisex)" data-dimension48="1460 8 Eye Boot (Unisex)" data-dimension25="$151" href="https://www.amazon.com/Dr-Martens-Smooth-Combat-Womens/dp/B004SI1QNU/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:684px;"><p class="vanilla-image-block" style="padding-top:101.61%;"><img id="imnJnaGkotNWgHnjsGETSk" name="1460 8 Eye Boot" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/imnJnaGkotNWgHnjsGETSk-1920-80.jpg" mos="" align="middle" fullscreen="" width="684" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Dr-Martens-Smooth-Combat-Womens/dp/B004SI1QNU/" target="_blank" rel="nofollow" data-dimension112="2c3ac850-d12f-11f1-a753-47a3eccd64c4" data-action="Deal Block" data-label="1460 8 Eye Boot (Unisex)" data-dimension48="1460 8 Eye Boot (Unisex)" data-dimension25="$151">1460 8 Eye Boot (Unisex): was $180 now $151</a></strong><br />Right now Dr. Martens’ 1460 8 Eye Boots have seen a discount at Amazon. Made of vegan leather, their slip-resistant soles and tough construction make them great for both work and everyday wear.<a class="view-deal button" href="https://www.amazon.com/Dr-Martens-Smooth-Combat-Womens/dp/B004SI1QNU/" target="_blank" rel="nofollow" data-dimension112="2c3ac850-d12f-11f1-a753-47a3eccd64c4" data-action="Deal Block" data-label="1460 8 Eye Boot (Unisex)" data-dimension48="1460 8 Eye Boot (Unisex)" data-dimension25="$151">View Deal</a></p></div><h3 class="article-body__section" id="section-timberland"><span>Timberland</span></h3><div class="product"><a data-dimension112="2c3ac90e-d12f-11f1-85a3-9fe1d961f60d" data-action="Deal Block" data-label="Davis Square Chukka Shoe (Men's)" data-dimension48="Davis Square Chukka Shoe (Men's)" data-dimension25="$48" href="https://www.amazon.com/Timberland-Davis-Square-Chukka-Wheat/dp/B0D54GMPLS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:895px;"><p class="vanilla-image-block" style="padding-top:77.65%;"><img id="9sA8mqcAuQkkDAVnQjVBqj" name="Davis Square Chukka Shoe (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/9sA8mqcAuQkkDAVnQjVBqj-1920-80.jpg" mos="" align="middle" fullscreen="" width="895" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Timberland-Davis-Square-Chukka-Wheat/dp/B0D54GMPLS" target="_blank" rel="nofollow" data-dimension112="2c3ac90e-d12f-11f1-85a3-9fe1d961f60d" data-action="Deal Block" data-label="Davis Square Chukka Shoe (Men's)" data-dimension48="Davis Square Chukka Shoe (Men's)" data-dimension25="$48">Davis Square Chukka Shoe (Men's): was $95 now $48</a></strong><br />Classic, stylish and comfortable. It doesn't get better than the Davis Square Chukka Shoe — especially when you can get a pair for almost half off. These are made of premium Timberland leather and have comfortable OrthoLite insoles.<a class="view-deal button" href="https://www.amazon.com/Timberland-Davis-Square-Chukka-Wheat/dp/B0D54GMPLS" target="_blank" rel="nofollow" data-dimension112="2c3ac90e-d12f-11f1-85a3-9fe1d961f60d" data-action="Deal Block" data-label="Davis Square Chukka Shoe (Men's)" data-dimension48="Davis Square Chukka Shoe (Men's)" data-dimension25="$48">View Deal</a></p></div><div class="product"><a data-dimension112="2c3ac968-d12f-11f1-89ec-eb419ee77651" data-action="Deal Block" data-label="Parker Street Mid Lace-Up Sneaker (Men's)" data-dimension48="Parker Street Mid Lace-Up Sneaker (Men's)" data-dimension25="$79" href="https://www.amazon.com/Timberland-Parker-Street-Lace-Up-Sneaker/dp/B0D54KCZDX" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:785px;"><p class="vanilla-image-block" style="padding-top:88.54%;"><img id="hxmYG96im3MVZgN7nzYSRk" name="Parker Street Mid Lace-Up Sneaker (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hxmYG96im3MVZgN7nzYSRk-1920-80.jpg" mos="" align="middle" fullscreen="" width="785" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Timberland-Parker-Street-Lace-Up-Sneaker/dp/B0D54KCZDX" target="_blank" rel="nofollow" data-dimension112="2c3ac968-d12f-11f1-89ec-eb419ee77651" data-action="Deal Block" data-label="Parker Street Mid Lace-Up Sneaker (Men's)" data-dimension48="Parker Street Mid Lace-Up Sneaker (Men's)" data-dimension25="$79">Parker Street Mid Lace-Up Sneaker (Men's): was $110 now $79</a></strong><br />These casual sneaker boots are a great transitional shoe from mornings at the office to afternoons on the mountain. The lace up sneaker will be a staple in your wardrobe thanks to their cushioning. You'll want to wear them on every adventure. <a class="view-deal button" href="https://www.amazon.com/Timberland-Parker-Street-Lace-Up-Sneaker/dp/B0D54KCZDX" target="_blank" rel="nofollow" data-dimension112="2c3ac968-d12f-11f1-89ec-eb419ee77651" data-action="Deal Block" data-label="Parker Street Mid Lace-Up Sneaker (Men's)" data-dimension48="Parker Street Mid Lace-Up Sneaker (Men's)" data-dimension25="$79">View Deal</a></p></div><h3 class="article-body__section" id="section-asics"><span>Asics</span></h3><div class="product"><a data-dimension112="2c3aca1c-d12f-11f1-a9c7-55d9c57385b9" data-action="Deal Block" data-label="Tiger Runner II (Women's)" data-dimension48="Tiger Runner II (Women's)" data-dimension25="$59" href="https://www.amazon.com/ASICS-Womens-Runner-Sportstyle-Silver/dp/B0H3F1WSB3" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:682px;"><p class="vanilla-image-block" style="padding-top:75.07%;"><img id="vcT4ZrTkbB5kx6uGRWjquJ" name="asics tiger runner ii" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vcT4ZrTkbB5kx6uGRWjquJ-1920-80.png" mos="" align="middle" fullscreen="" width="682" height="512" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Runner-Sportstyle-Silver/dp/B0H3F1WSB3" target="_blank" rel="nofollow" data-dimension112="2c3aca1c-d12f-11f1-a9c7-55d9c57385b9" data-action="Deal Block" data-label="Tiger Runner II (Women's)" data-dimension48="Tiger Runner II (Women's)" data-dimension25="$59">Tiger Runner II (Women's): was $85 now $59</a></strong><br />Designed for everyday wear, these Asics sneakers are inspired by classic 80s jogging shoes. On the inside, they're packed with today's best cushioning and durability.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Runner-Sportstyle-Silver/dp/B0H3F1WSB3" target="_blank" rel="nofollow" data-dimension112="2c3aca1c-d12f-11f1-a9c7-55d9c57385b9" data-action="Deal Block" data-label="Tiger Runner II (Women's)" data-dimension48="Tiger Runner II (Women's)" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="2c3aca76-d12f-11f1-af2c-15d20261453c" data-action="Deal Block" data-label="Gel-Venture 11" data-dimension48="Gel-Venture 11" data-dimension25="$69" href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Carrier/dp/B0FV72G49S" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1146px;"><p class="vanilla-image-block" style="padding-top:75.04%;"><img id="44i7uWA8WvTqRemkvKZpV6" name="Gel-Venture 11" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/44i7uWA8WvTqRemkvKZpV6-1920-80.jpg" mos="" align="middle" fullscreen="" width="1146" height="860" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Asics Gel-Venture 11 are designed for everyday runs and walks! They have Amplifoam Plus midsole cushioning on board, and a 2mm higher stack height — 2mm of extra softness to absorb impact and keep you comfortable for hours.<a class="view-deal button" href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Carrier/dp/B0FV72G49S" target="_blank" rel="nofollow" data-dimension112="2c3aca76-d12f-11f1-af2c-15d20261453c" data-action="Deal Block" data-label="Gel-Venture 11" data-dimension48="Gel-Venture 11" data-dimension25="$69">View Deal</a></p></div><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Home+Appliances&amp;view_mode=savings_squad&amp;widget_title=Top+Deals+Handpicked+by+Our+Editors&amp;widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&amp;bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                if (externalUrl) {                   if (seenUrls.has(externalUrl)) return;                  seenUrls.add(externalUrl);                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || '',                   authorName: article.articleauthortext ? article.articleauthortext[0] : (article.articleauthor ? article.articleauthor[0] : ''),                   authorRole: article.articleauthorrole ? article.articleauthorrole[0] : '',                   authorImage: article.articleauthormedia ? article.articleauthormedia[0] : '',                   documentUrl: article.documenturl ? article.documenturl[0] : '',                   modifiedDate: article.contentmodifieddate || article.modifieddate || ''                });             });          });                    const airedaleBrandsList = Object.keys(overallBrandsCounts).map(b => ({              formatted_value: b,              count: overallBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness/21-walking-shoe-deals-with-up-to-61-percent-off-best-fall-sales-on-skechers-birkenstocks-and-new-balance</link>
                                                                            <description>
                            <![CDATA[ Don't miss your chance for big savings on walking shoes from top brands! I'm sharing the best sales to stay comfortable this fall. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">f9sgu5ArpDoUbrAnnpyks9</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/YiZ8NoWkDHwRU6c8tgPEin-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 26 Oct 2026 12:06:22 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Fitness]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                <author><![CDATA[ millie.daviswilliams@futurenet.com (Millie Davis-Williams) ]]></author>                    <dc:creator><![CDATA[ Millie Davis-Williams ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/WU6pa7hKuxs5ScCoqcXYWA-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Millie is a Deals Editor at Tom&#039;s Guide specializing in tech deals content. Based in London, Millie has spent a lifetime stubbornly refusing to pay full price on any possible purchase. She has years of searching for the best discounts on the latest and greatest phones, TVs and gadgets under her belt, and knows how to sort the best deals from the rest. Helping readers save on the products they want is her mission, whether it’s an Apple Watch or a new tablet.&lt;/p&gt;&lt;p&gt;Since working at Tom’s Guide, Millie has covered retail events like Prime Day, Black Friday and Cyber Monday extensively, meaning she knows the products readers are looking for and the best times of year to hit “purchase.”&lt;/p&gt;&lt;p&gt;When she’s not looking for discounts, Millie covers news and writes how-to articles about everything from phones, streaming devices, and headphones to apps and video games.&lt;/p&gt;&lt;p&gt;In her spare time, Millie enjoys reading, gaming on her Nintendo Switch and creating digital art. She’s also a fan of watching Disney movies and collecting plush (the latter having totally taken over her bedroom.)&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/YiZ8NoWkDHwRU6c8tgPEin-1920-80.jpg">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[White Skechers sneakers]]></media:description>                                                            <media:text><![CDATA[White Skechers sneakers]]></media:text>
                                <media:title type="plain"><![CDATA[White Skechers sneakers]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/YiZ8NoWkDHwRU6c8tgPEin-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Fall is well and truly here. But that doesn't mean you have to hole up inside for the rest of the year. To keep enjoying the great outdoors, there are a bunch of deals you can grab on walking shoes from Skechers, Birkenstocks and more.</p><p>Over at <a href="https://www.amazon.com/b?node=211953829011" target="_blank" rel="nofollow">Amazon you'll find discounts on everything from Skechers slip-ins to Dr. Martens boots</a>. So if you need a new pair, I'm sharing the best savings below!</p><p><strong>Note: </strong>prices can vary depending on the size and color you select. To find the best deals, check out the different colors available in your size.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links </span></h3><ul><li><strong>Asics: </strong><a href="https://www.asics.com/us/en-us/clearance/c/aa60000000/?" target="_blank" rel="nofollow"><strong>deals from $49</strong></a></li><li><strong>Brooks: </strong><a href="https://www.amazon.com/stores/Brooks/page/B6834DFA-396F-4E38-98F6-3D2739393271?" target="_blank" rel="nofollow"><strong>up to 40% off</strong></a></li><li><strong>Hoka: </strong><a href="https://www.hoka.com/en/us/sale/" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li><li><strong>Nike: </strong><a href="https://www.nike.com/w/mens-shoes-nik1zy7ok" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li><li><strong>New Balance: </strong><a href="https://www.amazon.com/stores/NewBalanceAthleticShoeInc/page/855D4CDF-ADB7-4BE8-9E26-A085D029E4B5" target="_blank" rel="nofollow"><strong>deals from $39</strong></a></li><li><strong>Skechers: </strong><a href="https://www.skechers.com/women/shop-by-activity/walking/" target="_blank" rel="nofollow"><strong>20% off for members</strong></a></li></ul><h3 class="article-body__section" id="section-skechers"><span>Skechers</span></h3><div class="product"><a data-dimension112="2c3abf7c-d12f-11f1-b55a-c77191e28df0" data-action="Deal Block" data-label="Hands Free Slip-in Ultra Flex 3.0 - Brilliant Path Sneakers (Women's)" data-dimension48="Hands Free Slip-in Ultra Flex 3.0 - Brilliant Path Sneakers (Women's)" data-dimension25="$37" href="https://www.amazon.com/Skechers-Womens-BrilliantPath-Sneaker-Periwinkle/dp/B0CB1TB6FF" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:64.60%;"><img id="ktgq75pP2AA2yCeBTtmCNi" name="Hands Free Slip-in Ultra Flex 3.0 - Brilliant Path Sneakers (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ktgq75pP2AA2yCeBTtmCNi-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="449" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-BrilliantPath-Sneaker-Periwinkle/dp/B0CB1TB6FF" target="_blank" rel="nofollow" data-dimension112="2c3abf7c-d12f-11f1-b55a-c77191e28df0" data-action="Deal Block" data-label="Hands Free Slip-in Ultra Flex 3.0 - Brilliant Path Sneakers (Women's)" data-dimension48="Hands Free Slip-in Ultra Flex 3.0 - Brilliant Path Sneakers (Women's)" data-dimension25="$37">Hands Free Slip-in Ultra Flex 3.0 - Brilliant Path Sneakers (Women's): was $39 now $37</a></strong><br />The Skechers Ultra Flex 3.0 Brilliant Path slip-ons are our choice for the most versatile Skechers sneaker. As you'd expect, they're lightweight and comfortable with pillowy soft midsoles and Air-Cooled Memory Foam. In our <a href="https://www.tomsguide.com/reviews/Skechers-Slip-Ins-Ultra-Flex-3.0">Skechers Hands Free Ultra Flex 3.0 Brilliant Path review</a> we determined that they're great for casual wear, but we don't recommend them for high-impact exercise.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-BrilliantPath-Sneaker-Periwinkle/dp/B0CB1TB6FF" target="_blank" rel="nofollow" data-dimension112="2c3abf7c-d12f-11f1-b55a-c77191e28df0" data-action="Deal Block" data-label="Hands Free Slip-in Ultra Flex 3.0 - Brilliant Path Sneakers (Women's)" data-dimension48="Hands Free Slip-in Ultra Flex 3.0 - Brilliant Path Sneakers (Women's)" data-dimension25="$37">View Deal</a></p></div><div class="product"><a data-dimension112="2c3ac012-d12f-11f1-b9d7-d9a0451e464c" data-action="Deal Block" data-label="Go Walk Joy Cushioning Sneakers (Women's)" data-dimension48="Go Walk Joy Cushioning Sneakers (Women's)" data-dimension25="$44" href="https://www.amazon.com/Skechers-Sneaker-5Gen-Cushioning-Air-Cooled-Breathable/dp/B072LFYC5Q" 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:65.54%;"><img id="sMKHY4Hdbe52xJSyHG6eJg" name="81t7vPwv8wL._AC_SX679_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sMKHY4Hdbe52xJSyHG6eJg-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="445" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Sneaker-5Gen-Cushioning-Air-Cooled-Breathable/dp/B072LFYC5Q" target="_blank" rel="nofollow" data-dimension112="2c3ac012-d12f-11f1-b9d7-d9a0451e464c" data-action="Deal Block" data-label="Go Walk Joy Cushioning Sneakers (Women's)" data-dimension48="Go Walk Joy Cushioning Sneakers (Women's)" data-dimension25="$44">Go Walk Joy Cushioning Sneakers (Women's): was $51 now $44</a></strong><br />These slip-in Skechers shoes have all of the cushioning and comfort you've come to know and love from the brand. There's also a breathable upper, to keep your feet cool and comfortable.<a class="view-deal button" href="https://www.amazon.com/Skechers-Sneaker-5Gen-Cushioning-Air-Cooled-Breathable/dp/B072LFYC5Q" target="_blank" rel="nofollow" data-dimension112="2c3ac012-d12f-11f1-b9d7-d9a0451e464c" data-action="Deal Block" data-label="Go Walk Joy Cushioning Sneakers (Women's)" data-dimension48="Go Walk Joy Cushioning Sneakers (Women's)" data-dimension25="$44">View Deal</a></p></div><div class="product"><a data-dimension112="2c3ac076-d12f-11f1-9225-cdf77c0e89ee" data-action="Deal Block" data-label="Respected-Holmgren Slip-in Loafer (Men's)" data-dimension48="Respected-Holmgren Slip-in Loafer (Men's)" data-dimension25="$60" href="https://www.amazon.com/Skechers-Respected-Holmgren-Slip-Loafer-Charcoal/dp/B0BYBFZXL8" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1137px;"><p class="vanilla-image-block" style="padding-top:61.13%;"><img id="p79NadjFtsEoazJoKeBmgR" name="Respected-Holmgren Slip-in Loafer (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/p79NadjFtsEoazJoKeBmgR-1920-80.jpg" mos="" align="middle" fullscreen="" width="1137" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Respected-Holmgren-Slip-Loafer-Charcoal/dp/B0BYBFZXL8" target="_blank" rel="nofollow" data-dimension112="2c3ac076-d12f-11f1-9225-cdf77c0e89ee" data-action="Deal Block" data-label="Respected-Holmgren Slip-in Loafer (Men's)" data-dimension48="Respected-Holmgren Slip-in Loafer (Men's)" data-dimension25="$60">Respected-Holmgren Slip-in Loafer (Men's): was $89 now $60</a></strong><br />The simple but stylish design of the Respected-Holmgren Slip-in Loafer makes them a great pick for any activity. The Air Cooled Memory Foam delivers breathable comfort, and the Goodyear rubber outsole provides reliable grip in wet or icy conditions.<a class="view-deal button" href="https://www.amazon.com/Skechers-Respected-Holmgren-Slip-Loafer-Charcoal/dp/B0BYBFZXL8" target="_blank" rel="nofollow" data-dimension112="2c3ac076-d12f-11f1-9225-cdf77c0e89ee" data-action="Deal Block" data-label="Respected-Holmgren Slip-in Loafer (Men's)" data-dimension48="Respected-Holmgren Slip-in Loafer (Men's)" data-dimension25="$60">View Deal</a></p></div><div class="product"><a data-dimension112="558f67c2-d131-11f1-8c70-6fe2d258a912" data-action="Deal Block" data-label="Arch Fit 2.0 - Star Bound" data-dimension48="Arch Fit 2.0 - Star Bound" data-dimension25="$94" href="https://www.amazon.com/Skechers-Womens-Sneaker-White-7/dp/B0CPJFGK3G/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:819px;"><p class="vanilla-image-block" style="padding-top:84.86%;"><img id="VJnWP38VkGWMuARJrWadJB" name="Skechers Arch Fit 2.0 - Star Bound" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/VJnWP38VkGWMuARJrWadJB-1920-80.jpg" mos="" align="middle" fullscreen="" width="819" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Sneaker-White-7/dp/B0CPJFGK3G/" target="_blank" rel="nofollow" data-dimension112="558f67c2-d131-11f1-8c70-6fe2d258a912" data-action="Deal Block" data-label="Arch Fit 2.0 - Star Bound" data-dimension48="Arch Fit 2.0 - Star Bound" data-dimension25="$94">Arch Fit 2.0 - Star Bound: was $102 now $94</a></strong><br />The <a href="https://www.tomsguide.com/wellness/fitness/skechers-arch-fit-2-0-star-bound-review">Skechers Arch Fit 2.0 Star Bound</a> sneakers offer comfort and support for anyone looking for a versatile option to wear to run errands all day. The Air Cooled Memory Foam and Arch Fit technology work together to provide a bouncy walking experience, and the elevated heel aids in maintaining good posture by promoting heel-to-toe steps. The leather of the upper takes a little time to bend with your footsteps, but once it does, you will reach for them every day.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Sneaker-White-7/dp/B0CPJFGK3G/" target="_blank" rel="nofollow" data-dimension112="558f67c2-d131-11f1-8c70-6fe2d258a912" data-action="Deal Block" data-label="Arch Fit 2.0 - Star Bound" data-dimension48="Arch Fit 2.0 - Star Bound" data-dimension25="$94">View Deal</a></p></div><h3 class="article-body__section" id="section-birkenstocks"><span>Birkenstocks</span></h3><div class="product"><a data-dimension112="2c3ac134-d12f-11f1-9174-094bd5538ab4" data-action="Deal Block" data-label="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension48="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension25="$30" href="https://www.nordstromrack.com/s/birkenstock-arizona-stealth-buckle-eva-slide-sandal-women/7945865?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1560px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="3Qt2UrH7ESWm55JQpi8aXQ" name="Arizona Stealth" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3Qt2UrH7ESWm55JQpi8aXQ-1920-80.jpg" mos="" align="middle" fullscreen="" width="1560" height="2340" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nordstromrack.com/s/birkenstock-arizona-stealth-buckle-eva-slide-sandal-women/7945865?" target="_blank" rel="nofollow" data-dimension112="2c3ac134-d12f-11f1-9174-094bd5538ab4" data-action="Deal Block" data-label="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension48="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension25="$30">Arizona Stealth Buckle EVA Slide (Women's): was $54 now $30</a></strong><br />A pair of Birkenstocks for $30??? Sign me up. These waterproof slides are perfect for hanging out indoors, or going to the beach or pool. They feature a rubber-like texture with sleek adjustable straps and a grippy traction sole. <a class="view-deal button" href="https://www.nordstromrack.com/s/birkenstock-arizona-stealth-buckle-eva-slide-sandal-women/7945865?" target="_blank" rel="nofollow" data-dimension112="2c3ac134-d12f-11f1-9174-094bd5538ab4" data-action="Deal Block" data-label="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension48="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension25="$30">View Deal</a></p></div><div class="product"><a data-dimension112="508c7720-d130-11f1-aa16-1d13b2533b71" data-action="Deal Block" data-label="Lutry 365 Clog - Suede (Women's)" data-dimension48="Lutry 365 Clog - Suede (Women's)" data-dimension25="$61" href="https://www.amazon.com/Birkenstock-Womens-Lutry-365-Suede-Narrow/dp/B0FH15W1SY" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:46.62%;"><img id="b4FtpSQLYePgojSeRWMMh8" name="Lutry 365 Clog - Suede (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/b4FtpSQLYePgojSeRWMMh8-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="324" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Birkenstock-Womens-Lutry-365-Suede-Narrow/dp/B0FH15W1SY" target="_blank" rel="nofollow" data-dimension112="508c7720-d130-11f1-aa16-1d13b2533b71" data-action="Deal Block" data-label="Lutry 365 Clog - Suede (Women's)" data-dimension48="Lutry 365 Clog - Suede (Women's)" data-dimension25="$61">Lutry 365 Clog - Suede (Women's): was $154 now $61</a></strong><br />You don't see a Birkenstock discount this big every day, so grab it while you can if it's available in your size! These slip-on clogs have a premium suede upper, making them look and feel super luxurious.<a class="view-deal button" href="https://www.amazon.com/Birkenstock-Womens-Lutry-365-Suede-Narrow/dp/B0FH15W1SY" target="_blank" rel="nofollow" data-dimension112="508c7720-d130-11f1-aa16-1d13b2533b71" data-action="Deal Block" data-label="Lutry 365 Clog - Suede (Women's)" data-dimension48="Lutry 365 Clog - Suede (Women's)" data-dimension25="$61">View Deal</a></p></div><div class="product"><a data-dimension112="2c3ac1b6-d12f-11f1-b4df-f9cca801955f" data-action="Deal Block" data-label="Papilio Florida Platform Flex (Women's)" data-dimension48="Papilio Florida Platform Flex (Women's)" data-dimension25="$74" href="https://www.nordstromrack.com/s/florida-flex-platform-slide-sandal-women/7953334?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1560px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="YToScW8bDWGEAAJqToJey" name="florida" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/YToScW8bDWGEAAJqToJey-1920-80.jpg" mos="" align="middle" fullscreen="" width="1560" height="2340" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nordstromrack.com/s/florida-flex-platform-slide-sandal-women/7953334?" target="_blank" rel="nofollow" data-dimension112="2c3ac1b6-d12f-11f1-b4df-f9cca801955f" data-action="Deal Block" data-label="Papilio Florida Platform Flex (Women's)" data-dimension48="Papilio Florida Platform Flex (Women's)" data-dimension25="$74">Papilio Florida Platform Flex (Women's): was $144 now $74</a></strong><br />These Papilio by Birkenstock sandals feature a platform and three straps for extra support. Reviewers love their iconic design and comfortable, adjustable fit.<a class="view-deal button" href="https://www.nordstromrack.com/s/florida-flex-platform-slide-sandal-women/7953334?" target="_blank" rel="nofollow" data-dimension112="2c3ac1b6-d12f-11f1-b4df-f9cca801955f" data-action="Deal Block" data-label="Papilio Florida Platform Flex (Women's)" data-dimension48="Papilio Florida Platform Flex (Women's)" data-dimension25="$74">View Deal</a></p></div><h3 class="article-body__section" id="section-vans"><span>Vans</span></h3><div class="product"><a data-dimension112="508c7bc6-d130-11f1-b083-a1a8585d05a8" data-action="Deal Block" data-label="Asher Adult Low Top Sneakers (Women's)" data-dimension48="Asher Adult Low Top Sneakers (Women's)" data-dimension25="$39" href="https://www.amazon.com/Vans-Comfortable-Sneakers-Walking-Everyday/dp/B0FL84PVY7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1047px;"><p class="vanilla-image-block" style="padding-top:66.38%;"><img id="QKub3ycPjdDp9fUWpA3uZc" name="Asher Adult Low Top Sneakers (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/QKub3ycPjdDp9fUWpA3uZc-1920-80.jpg" mos="" align="middle" fullscreen="" width="1047" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Vans-Comfortable-Sneakers-Walking-Everyday/dp/B0FL84PVY7" target="_blank" rel="nofollow" data-dimension112="508c7bc6-d130-11f1-b083-a1a8585d05a8" data-action="Deal Block" data-label="Asher Adult Low Top Sneakers (Women's)" data-dimension48="Asher Adult Low Top Sneakers (Women's)" data-dimension25="$39">Asher Adult Low Top Sneakers (Women's): was $55 now $39</a></strong><br />Vans' low-top slip-on shoes are a steal starting from just $39! The simple design means they couldn't be any more versatile and easy to style — and the color selection is great, too. <a class="view-deal button" href="https://www.amazon.com/Vans-Comfortable-Sneakers-Walking-Everyday/dp/B0FL84PVY7" target="_blank" rel="nofollow" data-dimension112="508c7bc6-d130-11f1-b083-a1a8585d05a8" data-action="Deal Block" data-label="Asher Adult Low Top Sneakers (Women's)" data-dimension48="Asher Adult Low Top Sneakers (Women's)" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="508c7c84-d130-11f1-8116-bb3e84775756" data-action="Deal Block" data-label="Brooklyn LS Shoe (Women's)" data-dimension48="Brooklyn LS Shoe (Women's)" data-dimension25="$52" href="https://www.amazon.com/Vans-Brooklyn-Low-Top-Sneakers-Everyday/dp/B0D7QCNLHJ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1005px;"><p class="vanilla-image-block" style="padding-top:69.15%;"><img id="rJDozMtKWunUE3PrvRZ9kQ" name="Brooklyn LS Shoe (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/rJDozMtKWunUE3PrvRZ9kQ-1920-80.jpg" mos="" align="middle" fullscreen="" width="1005" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Vans-Brooklyn-Low-Top-Sneakers-Everyday/dp/B0D7QCNLHJ" target="_blank" rel="nofollow" data-dimension112="508c7c84-d130-11f1-8116-bb3e84775756" data-action="Deal Block" data-label="Brooklyn LS Shoe (Women's)" data-dimension48="Brooklyn LS Shoe (Women's)" data-dimension25="$52">Brooklyn LS Shoe (Women's): was $70 now $52</a></strong><br />These classic Vans can be yours starting from just $52 right now. Their padded collar makes them comfortable to wear, and they feature the iconic Vans stripe down the side.<a class="view-deal button" href="https://www.amazon.com/Vans-Brooklyn-Low-Top-Sneakers-Everyday/dp/B0D7QCNLHJ" target="_blank" rel="nofollow" data-dimension112="508c7c84-d130-11f1-8116-bb3e84775756" data-action="Deal Block" data-label="Brooklyn LS Shoe (Women's)" data-dimension48="Brooklyn LS Shoe (Women's)" data-dimension25="$52">View Deal</a></p></div><h3 class="article-body__section" id="section-cushionaire"><span>Cushionaire</span></h3><div class="product"><a data-dimension112="2c3ac3fa-d12f-11f1-9469-391b5c391713" data-action="Deal Block" data-label="Laz Cork Footbed Sandals" data-dimension48="Laz Cork Footbed Sandals" data-dimension25="$39" href="https://www.amazon.com/dp/B0H8FB19F7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:606px;"><p class="vanilla-image-block" style="padding-top:114.69%;"><img id="GknzxZr7RhbEEsFqQG3HjN" name="Laz" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/GknzxZr7RhbEEsFqQG3HjN-1920-80.jpg" mos="" align="middle" fullscreen="" width="606" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0H8FB19F7" target="_blank" rel="nofollow" data-dimension112="2c3ac3fa-d12f-11f1-9469-391b5c391713" data-action="Deal Block" data-label="Laz Cork Footbed Sandals" data-dimension48="Laz Cork Footbed Sandals" data-dimension25="$39">Laz Cork Footbed Sandals: was $59 now $39</a></strong><br />If you're in the market for some Birkenstocks but don't want to pay the hefty price, these Cushionaire sandals are the next best thing. Crafted from high-quality faux leather, the sandals feature a soft lining and adjustable double buckle strap. They're also available in a plethora of colors, although price may vary. <a class="view-deal button" href="https://www.amazon.com/dp/B0H8FB19F7" target="_blank" rel="nofollow" data-dimension112="2c3ac3fa-d12f-11f1-9469-391b5c391713" data-action="Deal Block" data-label="Laz Cork Footbed Sandals" data-dimension48="Laz Cork Footbed Sandals" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="2c3ac45e-d12f-11f1-a100-c3e3fffc96dc" data-action="Deal Block" data-label="Lens Sandals" data-dimension48="Lens Sandals" data-dimension25="$49" href="https://www.amazon.com/dp/B0GZJ8VB6M" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:543px;"><p class="vanilla-image-block" style="padding-top:127.99%;"><img id="v9a622fikJvyBJaGFHRcpH" name="Cushionaire Lens" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/v9a622fikJvyBJaGFHRcpH-1920-80.jpg" mos="" align="middle" fullscreen="" width="543" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0GZJ8VB6M" target="_blank" rel="nofollow" data-dimension112="2c3ac45e-d12f-11f1-a100-c3e3fffc96dc" data-action="Deal Block" data-label="Lens Sandals" data-dimension48="Lens Sandals" data-dimension25="$49">Lens Sandals: was $69 now $49</a></strong><br />Looking for a fun little twist on a classic slide? Slip into these comfortable sandals that feature unique braided straps. They have a cushioned footbed and a contoured sole making them extra comfy. They also pair nicely with dresses, denim and casual outfits.<a class="view-deal button" href="https://www.amazon.com/dp/B0GZJ8VB6M" target="_blank" rel="nofollow" data-dimension112="2c3ac45e-d12f-11f1-a100-c3e3fffc96dc" data-action="Deal Block" data-label="Lens Sandals" data-dimension48="Lens Sandals" data-dimension25="$49">View Deal</a></p></div><h3 class="article-body__section" id="section-nortiv-8"><span>Nortiv 8</span></h3><div class="product"><a data-dimension112="2c3ac512-d12f-11f1-b603-b1ccc341b16a" data-action="Deal Block" data-label="Lightweight Ankle Hiking Boots (Women's)" data-dimension48="Lightweight Ankle Hiking Boots (Women's)" data-dimension25="$39" href="https://www.amazon.com/dp/B0BFPR8Y2Y" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:873px;"><p class="vanilla-image-block" style="padding-top:79.61%;"><img id="5QdW6J7JmJEfcovDJA6ZgM" name="Lightweight Ankle Hiking Boots (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/5QdW6J7JmJEfcovDJA6ZgM-1920-80.jpg" mos="" align="middle" fullscreen="" width="873" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0BFPR8Y2Y" target="_blank" rel="nofollow" data-dimension112="2c3ac512-d12f-11f1-b603-b1ccc341b16a" data-action="Deal Block" data-label="Lightweight Ankle Hiking Boots (Women's)" data-dimension48="Lightweight Ankle Hiking Boots (Women's)" data-dimension25="$39">Lightweight Ankle Hiking Boots (Women's): was $47 now $39</a></strong><br />Nortiv 8's budget-friendly hiking boots just got a discount, making them even better value. They're built to be lightweight, comfortable and durable, with grip to stop you from slipping on the trails.<a class="view-deal button" href="https://www.amazon.com/dp/B0BFPR8Y2Y" target="_blank" rel="nofollow" data-dimension112="2c3ac512-d12f-11f1-b603-b1ccc341b16a" data-action="Deal Block" data-label="Lightweight Ankle Hiking Boots (Women's)" data-dimension48="Lightweight Ankle Hiking Boots (Women's)" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="2c3ac56c-d12f-11f1-b6ca-9fc55314d528" data-action="Deal Block" data-label="Trail Running Walking Shoes (Men's)" data-dimension48="Trail Running Walking Shoes (Men's)" data-dimension25="$56" href="https://www.amazon.com/dp/B0H7BRYLZ1" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1093px;"><p class="vanilla-image-block" style="padding-top:63.59%;"><img id="98qPHFxV2Ykz8EZjKZouLY" name="Trail Running Walking Shoes (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/98qPHFxV2Ykz8EZjKZouLY-1920-80.jpg" mos="" align="middle" fullscreen="" width="1093" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0H7BRYLZ1" target="_blank" rel="nofollow" data-dimension112="2c3ac56c-d12f-11f1-b6ca-9fc55314d528" data-action="Deal Block" data-label="Trail Running Walking Shoes (Men's)" data-dimension48="Trail Running Walking Shoes (Men's)" data-dimension25="$56">Trail Running Walking Shoes (Men's): was $69 now $56</a></strong><br />These Nortiv 8 shoes come in handy for both hiking and trail runs. They're lightweight, packed with cushioning and have grip to keep you steady. Plus, with this discount, they're affordable too.<a class="view-deal button" href="https://www.amazon.com/dp/B0H7BRYLZ1" target="_blank" rel="nofollow" data-dimension112="2c3ac56c-d12f-11f1-b6ca-9fc55314d528" data-action="Deal Block" data-label="Trail Running Walking Shoes (Men's)" data-dimension48="Trail Running Walking Shoes (Men's)" data-dimension25="$56">View Deal</a></p></div><h3 class="article-body__section" id="section-new-balance"><span>New Balance</span></h3><div class="product"><a data-dimension112="2c3ac62a-d12f-11f1-8a8b-77e3e9abadb3" data-action="Deal Block" data-label="237 V1 Sneaker (Men's)" data-dimension48="237 V1 Sneaker (Men's)" data-dimension25="$69" href="https://www.amazon.com/New-Balance-Sneaker-White-Brighton/dp/B0F4MB4R6V" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1290px;"><p class="vanilla-image-block" style="padding-top:50.47%;"><img id="sTxmZw69B2s8LpTEsCvTfT" name="237 V1 Sneaker (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sTxmZw69B2s8LpTEsCvTfT-1920-80.jpg" mos="" align="middle" fullscreen="" width="1290" height="651" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-Sneaker-White-Brighton/dp/B0F4MB4R6V" target="_blank" rel="nofollow" data-dimension112="2c3ac62a-d12f-11f1-8a8b-77e3e9abadb3" data-action="Deal Block" data-label="237 V1 Sneaker (Men's)" data-dimension48="237 V1 Sneaker (Men's)" data-dimension25="$69">237 V1 Sneaker (Men's): was $84 now $69</a></strong><br />Right now you can get the New Balance 237 V1 sneakers on sale and add a touch of style to your wardrobe. They have a suede and mesh upper with a sleek three-tone color scheme.<a class="view-deal button" href="https://www.amazon.com/New-Balance-Sneaker-White-Brighton/dp/B0F4MB4R6V" target="_blank" rel="nofollow" data-dimension112="2c3ac62a-d12f-11f1-8a8b-77e3e9abadb3" data-action="Deal Block" data-label="237 V1 Sneaker (Men's)" data-dimension48="237 V1 Sneaker (Men's)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="2c3ac684-d12f-11f1-a5d7-ff54bdfdf464" data-action="Deal Block" data-label="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension48="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension25="$98" href="https://www.amazon.com/New-Balance-FuelCell-Walking-Electric/dp/B0D2Y7L3DC" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:755px;"><p class="vanilla-image-block" style="padding-top:55.23%;"><img id="ufsfox6NerPUoEY6YYZYXk" name="FuelCell Walker Elite V1 Walking Shoe (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ufsfox6NerPUoEY6YYZYXk-1920-80.jpg" mos="" align="middle" fullscreen="" width="755" height="417" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-FuelCell-Walking-Electric/dp/B0D2Y7L3DC" target="_blank" rel="nofollow" data-dimension112="2c3ac684-d12f-11f1-a5d7-ff54bdfdf464" data-action="Deal Block" data-label="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension48="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension25="$98">FuelCell Walker Elite V1 Walking Shoe (Women's): was $139 now $98</a></strong><br />Engineered for walking, the New Balance FuelCell Walker Elite V1 Walking Shoes are cushioned, stable, and propel your feet forward with each step. They look super sleek, too. <a class="view-deal button" href="https://www.amazon.com/New-Balance-FuelCell-Walking-Electric/dp/B0D2Y7L3DC" target="_blank" rel="nofollow" data-dimension112="2c3ac684-d12f-11f1-a5d7-ff54bdfdf464" data-action="Deal Block" data-label="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension48="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension25="$98">View Deal</a></p></div><h3 class="article-body__section" id="section-dr-martens"><span>Dr Martens</span></h3><div class="product"><a data-dimension112="2c3ac7e2-d12f-11f1-9654-3b855454325c" data-action="Deal Block" data-label="Holly Leather Quad Shoe (Women's)" data-dimension48="Holly Leather Quad Shoe (Women's)" data-dimension25="$83" href="https://www.amazon.com/Dr-Martens-Holly-Buttero-Womens/dp/B07MHM313L" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:72.37%;"><img id="AgdKAuExiUftz8NTZy4PoQ" name="Holly Leather Quad Shoe (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/AgdKAuExiUftz8NTZy4PoQ-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="503" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Dr-Martens-Holly-Buttero-Womens/dp/B07MHM313L" target="_blank" rel="nofollow" data-dimension112="2c3ac7e2-d12f-11f1-9654-3b855454325c" data-action="Deal Block" data-label="Holly Leather Quad Shoe (Women's)" data-dimension48="Holly Leather Quad Shoe (Women's)" data-dimension25="$83">Holly Leather Quad Shoe (Women's): was $170 now $83</a></strong><br />Don't miss your chance to score this huge saving — it's not going to be available for long. These Dr Martens shoes have 1.5-inch soles and a pretty ribbon at the front! Perfect to add some "dark academia" vibes to your fall outfits.<a class="view-deal button" href="https://www.amazon.com/Dr-Martens-Holly-Buttero-Womens/dp/B07MHM313L" target="_blank" rel="nofollow" data-dimension112="2c3ac7e2-d12f-11f1-9654-3b855454325c" data-action="Deal Block" data-label="Holly Leather Quad Shoe (Women's)" data-dimension48="Holly Leather Quad Shoe (Women's)" data-dimension25="$83">View Deal</a></p></div><div class="product"><a data-dimension112="2c3ac850-d12f-11f1-a753-47a3eccd64c4" data-action="Deal Block" data-label="1460 8 Eye Boot (Unisex)" data-dimension48="1460 8 Eye Boot (Unisex)" data-dimension25="$151" href="https://www.amazon.com/Dr-Martens-Smooth-Combat-Womens/dp/B004SI1QNU/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:684px;"><p class="vanilla-image-block" style="padding-top:101.61%;"><img id="imnJnaGkotNWgHnjsGETSk" name="1460 8 Eye Boot" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/imnJnaGkotNWgHnjsGETSk-1920-80.jpg" mos="" align="middle" fullscreen="" width="684" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Dr-Martens-Smooth-Combat-Womens/dp/B004SI1QNU/" target="_blank" rel="nofollow" data-dimension112="2c3ac850-d12f-11f1-a753-47a3eccd64c4" data-action="Deal Block" data-label="1460 8 Eye Boot (Unisex)" data-dimension48="1460 8 Eye Boot (Unisex)" data-dimension25="$151">1460 8 Eye Boot (Unisex): was $180 now $151</a></strong><br />Right now Dr. Martens’ 1460 8 Eye Boots have seen a discount at Amazon. Made of vegan leather, their slip-resistant soles and tough construction make them great for both work and everyday wear.<a class="view-deal button" href="https://www.amazon.com/Dr-Martens-Smooth-Combat-Womens/dp/B004SI1QNU/" target="_blank" rel="nofollow" data-dimension112="2c3ac850-d12f-11f1-a753-47a3eccd64c4" data-action="Deal Block" data-label="1460 8 Eye Boot (Unisex)" data-dimension48="1460 8 Eye Boot (Unisex)" data-dimension25="$151">View Deal</a></p></div><h3 class="article-body__section" id="section-timberland"><span>Timberland</span></h3><div class="product"><a data-dimension112="2c3ac90e-d12f-11f1-85a3-9fe1d961f60d" data-action="Deal Block" data-label="Davis Square Chukka Shoe (Men's)" data-dimension48="Davis Square Chukka Shoe (Men's)" data-dimension25="$48" href="https://www.amazon.com/Timberland-Davis-Square-Chukka-Wheat/dp/B0D54GMPLS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:895px;"><p class="vanilla-image-block" style="padding-top:77.65%;"><img id="9sA8mqcAuQkkDAVnQjVBqj" name="Davis Square Chukka Shoe (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/9sA8mqcAuQkkDAVnQjVBqj-1920-80.jpg" mos="" align="middle" fullscreen="" width="895" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Timberland-Davis-Square-Chukka-Wheat/dp/B0D54GMPLS" target="_blank" rel="nofollow" data-dimension112="2c3ac90e-d12f-11f1-85a3-9fe1d961f60d" data-action="Deal Block" data-label="Davis Square Chukka Shoe (Men's)" data-dimension48="Davis Square Chukka Shoe (Men's)" data-dimension25="$48">Davis Square Chukka Shoe (Men's): was $95 now $48</a></strong><br />Classic, stylish and comfortable. It doesn't get better than the Davis Square Chukka Shoe — especially when you can get a pair for almost half off. These are made of premium Timberland leather and have comfortable OrthoLite insoles.<a class="view-deal button" href="https://www.amazon.com/Timberland-Davis-Square-Chukka-Wheat/dp/B0D54GMPLS" target="_blank" rel="nofollow" data-dimension112="2c3ac90e-d12f-11f1-85a3-9fe1d961f60d" data-action="Deal Block" data-label="Davis Square Chukka Shoe (Men's)" data-dimension48="Davis Square Chukka Shoe (Men's)" data-dimension25="$48">View Deal</a></p></div><div class="product"><a data-dimension112="2c3ac968-d12f-11f1-89ec-eb419ee77651" data-action="Deal Block" data-label="Parker Street Mid Lace-Up Sneaker (Men's)" data-dimension48="Parker Street Mid Lace-Up Sneaker (Men's)" data-dimension25="$79" href="https://www.amazon.com/Timberland-Parker-Street-Lace-Up-Sneaker/dp/B0D54KCZDX" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:785px;"><p class="vanilla-image-block" style="padding-top:88.54%;"><img id="hxmYG96im3MVZgN7nzYSRk" name="Parker Street Mid Lace-Up Sneaker (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hxmYG96im3MVZgN7nzYSRk-1920-80.jpg" mos="" align="middle" fullscreen="" width="785" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Timberland-Parker-Street-Lace-Up-Sneaker/dp/B0D54KCZDX" target="_blank" rel="nofollow" data-dimension112="2c3ac968-d12f-11f1-89ec-eb419ee77651" data-action="Deal Block" data-label="Parker Street Mid Lace-Up Sneaker (Men's)" data-dimension48="Parker Street Mid Lace-Up Sneaker (Men's)" data-dimension25="$79">Parker Street Mid Lace-Up Sneaker (Men's): was $110 now $79</a></strong><br />These casual sneaker boots are a great transitional shoe from mornings at the office to afternoons on the mountain. The lace up sneaker will be a staple in your wardrobe thanks to their cushioning. You'll want to wear them on every adventure. <a class="view-deal button" href="https://www.amazon.com/Timberland-Parker-Street-Lace-Up-Sneaker/dp/B0D54KCZDX" target="_blank" rel="nofollow" data-dimension112="2c3ac968-d12f-11f1-89ec-eb419ee77651" data-action="Deal Block" data-label="Parker Street Mid Lace-Up Sneaker (Men's)" data-dimension48="Parker Street Mid Lace-Up Sneaker (Men's)" data-dimension25="$79">View Deal</a></p></div><h3 class="article-body__section" id="section-asics"><span>Asics</span></h3><div class="product"><a data-dimension112="2c3aca1c-d12f-11f1-a9c7-55d9c57385b9" data-action="Deal Block" data-label="Tiger Runner II (Women's)" data-dimension48="Tiger Runner II (Women's)" data-dimension25="$59" href="https://www.amazon.com/ASICS-Womens-Runner-Sportstyle-Silver/dp/B0H3F1WSB3" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:682px;"><p class="vanilla-image-block" style="padding-top:75.07%;"><img id="vcT4ZrTkbB5kx6uGRWjquJ" name="asics tiger runner ii" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vcT4ZrTkbB5kx6uGRWjquJ-1920-80.png" mos="" align="middle" fullscreen="" width="682" height="512" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Runner-Sportstyle-Silver/dp/B0H3F1WSB3" target="_blank" rel="nofollow" data-dimension112="2c3aca1c-d12f-11f1-a9c7-55d9c57385b9" data-action="Deal Block" data-label="Tiger Runner II (Women's)" data-dimension48="Tiger Runner II (Women's)" data-dimension25="$59">Tiger Runner II (Women's): was $85 now $59</a></strong><br />Designed for everyday wear, these Asics sneakers are inspired by classic 80s jogging shoes. On the inside, they're packed with today's best cushioning and durability.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Runner-Sportstyle-Silver/dp/B0H3F1WSB3" target="_blank" rel="nofollow" data-dimension112="2c3aca1c-d12f-11f1-a9c7-55d9c57385b9" data-action="Deal Block" data-label="Tiger Runner II (Women's)" data-dimension48="Tiger Runner II (Women's)" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="2c3aca76-d12f-11f1-af2c-15d20261453c" data-action="Deal Block" data-label="Gel-Venture 11" data-dimension48="Gel-Venture 11" data-dimension25="$69" href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Carrier/dp/B0FV72G49S" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1146px;"><p class="vanilla-image-block" style="padding-top:75.04%;"><img id="44i7uWA8WvTqRemkvKZpV6" name="Gel-Venture 11" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/44i7uWA8WvTqRemkvKZpV6-1920-80.jpg" mos="" align="middle" fullscreen="" width="1146" height="860" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Asics Gel-Venture 11 are designed for everyday runs and walks! They have Amplifoam Plus midsole cushioning on board, and a 2mm higher stack height — 2mm of extra softness to absorb impact and keep you comfortable for hours.<a class="view-deal button" href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Carrier/dp/B0FV72G49S" target="_blank" rel="nofollow" data-dimension112="2c3aca76-d12f-11f1-af2c-15d20261453c" data-action="Deal Block" data-label="Gel-Venture 11" data-dimension48="Gel-Venture 11" data-dimension25="$69">View Deal</a></p></div><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Home+Appliances&amp;view_mode=savings_squad&amp;widget_title=Top+Deals+Handpicked+by+Our+Editors&amp;widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&amp;bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                if (externalUrl) {                   if (seenUrls.has(externalUrl)) return;                  seenUrls.add(externalUrl);                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || '',                   authorName: article.articleauthortext ? article.articleauthortext[0] : (article.articleauthor ? article.articleauthor[0] : ''),                   authorRole: article.articleauthorrole ? article.articleauthorrole[0] : '',                   authorImage: article.articleauthormedia ? article.articleauthormedia[0] : '',                   documentUrl: article.documenturl ? article.documenturl[0] : '',                   modifiedDate: article.contentmodifieddate || article.modifieddate || ''                });             });          });                    const airedaleBrandsList = Object.keys(overallBrandsCounts).map(b => ({              formatted_value: b,              count: overallBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 15 best Patagonia deals at REI — save up to 50% on my favorite fall finds ]]></title>
                                                                                                <dc:content><![CDATA[ <p>REI is notorious for offering impressive markdowns on the best outdoor brands — and Patagonia is no exception. Now that temperatures are starting to drop, investing in some high-quality outerwear is a must. And fortunately, <a href="https://www.rei.com/b/patagonia/f/scd-deals?" target="_blank" rel="nofollow">Patagonia's best-selling styles are up to 50% off</a>. </p><p>For instance, <a href="https://www.rei.com/product/143470/patagonia-houdini-jacket-mens" target="_blank" rel="nofollow">the popular Patagonia Houdini Jacket is down to just $82</a> and is the perfect layer for fall adventures. You can also grab <a href="https://www.rei.com/product/242671/patagonia-micro-d-half-zip-fleece-pullover-womens" target="_blank" rel="nofollow">the Patagonia Micro-D Half-Zip Fleece Pullover for just $44</a>. Plus, there's plenty more deals on rain jackets, hats, hoodies and fleeces from $21.</p><p>Patagonia doesn't come cheap, so you'll want to snap up these deals ASAP.  Below, I've rounded up my favorite REI styles. Keep scrolling to check out the deals that are actually worth shopping for fall. </p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><a href="https://www.rei.com/f/scd-deals" target="_blank" rel="nofollow"><strong>shop REI's fall sale</strong></a></li><li><strong>Patagonia: </strong><a href="https://www.rei.com/b/patagonia/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;r=f%3Bb&amp;sort=min-price" target="_blank" rel="nofollow"><strong>apparel/accessories from $15</strong></a></li><li><strong>Camping gear: </strong><a href="https://www.rei.com/c/camping-and-hiking/f/scd-deals" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li><li><strong>Vuori: </strong><a href="https://www.rei.com/b/vuori/f/scd-deals?" target="_blank" rel="nofollow"><strong>up to 40% off</strong></a></li><li><strong>Arc'teryx: </strong><a href="https://www.rei.com/b/arcteryx/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;sort=min-price&amp;r=f%3Bb" target="_blank" rel="nofollow"><strong>apparel from $24</strong></a></li><li><strong>Columbia: </strong><a href="https://www.rei.com/b/columbia/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;sort=min-price&amp;irclickid=3KjxOUTuLxyKWYwT3BUaGy3DUkp2c0Uto0pyw40" target="_blank" rel="nofollow"><strong>apparel from $14</strong></a></li><li><strong>Marmot: </strong><a href="https://www.rei.com/b/marmot/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;sort=min-price&amp;r=f%3Bb" target="_blank" rel="nofollow"><strong>apparel from $15</strong></a></li><li><strong>The North Face: </strong><a href="https://www.rei.com/b/the-north-face/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;r=f%3Bb&amp;sort=min-price" target="_blank" rel="nofollow"><strong>apparel from $16</strong></a></li><li><strong>Yeti: </strong><a href="https://www.rei.com/b/yeti/f/scd-deals?" target="_blank" rel="nofollow"><strong>water bottles from $17</strong></a></li><li><strong>Saucony: </strong><a href="https://www.rei.com/b/saucony/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;sort=min-price&amp;r=f%3Bb" target="_blank" rel="nofollow"><strong>running gear from $46</strong></a><strong></strong></li></ul><h3 class="article-body__section" id="section-top-patagonia-deals"><span>Top Patagonia Deals</span></h3><div class="product"><a data-dimension112="5739ce20-cf13-11f1-a7ce-574d3763f097" data-action="Deal Block" data-label="Coastal Cable Beanie" data-dimension48="Coastal Cable Beanie" data-dimension25="$21" href="https://www.rei.com/product/240304/patagonia-coastal-cable-beanie" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:932px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="aBHmT9EnHGHJTKCk7hooyT" name="patagonia coastal cable beanie" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/aBHmT9EnHGHJTKCk7hooyT-1920-80.jpg" mos="" align="middle" fullscreen="" width="932" height="932" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>Made with recycled wool and recycled nylon, the Patagonia Coastal Cable beanie is super-warm and super-fuzzy, perfect for winter and fall. There's even a recycled fleece headband to keep the cold out and the warm in. The green color is eye-catching enough to ensure your friends will never lose you on the slopes or in the city. <a class="view-deal button" href="https://www.rei.com/product/240304/patagonia-coastal-cable-beanie" target="_blank" rel="nofollow" data-dimension112="5739ce20-cf13-11f1-a7ce-574d3763f097" data-action="Deal Block" data-label="Coastal Cable Beanie" data-dimension48="Coastal Cable Beanie" data-dimension25="$21">View Deal</a></p></div><div class="product"><a data-dimension112="5739ce8e-cf13-11f1-8e1c-5335e032695f" data-action="Deal Block" data-label="Powder Town Headband" data-dimension48="Powder Town Headband" data-dimension25="$22" href="https://www.rei.com/product/240312/patagonia-powder-town-headband" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:932px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="ekwiWeSPvjXJ3G4PTtqQXP" name="patagonia powder town headband" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ekwiWeSPvjXJ3G4PTtqQXP-1920-80.jpg" mos="" align="middle" fullscreen="" width="932" height="932" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Patagonia Powder Town Headband is designed to keep your ears warm on the slopes, without overheating the rest of you. It's also so bright that your friends will always be able to find you. This headband has a moisture-wicking recycled fleece lining to keep you dry and cozy. <a class="view-deal button" href="https://www.rei.com/product/240312/patagonia-powder-town-headband" target="_blank" rel="nofollow" data-dimension112="5739ce8e-cf13-11f1-8e1c-5335e032695f" data-action="Deal Block" data-label="Powder Town Headband" data-dimension48="Powder Town Headband" data-dimension25="$22">View Deal</a></p></div><div class="product"><a data-dimension112="5739cefc-cf13-11f1-bae6-3b754de32af0" data-action="Deal Block" data-label="Micro-D Half-Zip Fleece Pullover (Women's)" data-dimension48="Micro-D Half-Zip Fleece Pullover (Women's)" data-dimension25="$48" href="https://www.rei.com/product/242671/patagonia-micro-d-half-zip-fleece-pullover-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1576px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="nf39PweshXkywy2qiMnC8k" name="b28afb8f-ec50-4921-9346-b3269d66e19b" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/nf39PweshXkywy2qiMnC8k-1920-80.jpg" mos="" align="middle" fullscreen="" width="1576" height="1576" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/242671/patagonia-micro-d-half-zip-fleece-pullover-womens" target="_blank" rel="nofollow" data-dimension112="5739cefc-cf13-11f1-bae6-3b754de32af0" data-action="Deal Block" data-label="Micro-D Half-Zip Fleece Pullover (Women's)" data-dimension48="Micro-D Half-Zip Fleece Pullover (Women's)" data-dimension25="$48">Micro-D Half-Zip Fleece Pullover (Women's): was $99 now $48</a></strong><br />Right now, the beautiful Thin Ice colorway is down to $48 in REI’s mid-season deal. It’s still available in a handful of sizes. The <a href="https://www.rei.com/product/143319/patagonia-micro-d-fleece-pullover-mens%20" target="_blank" rel="nofollow">men’s Micro D Fleece Pullover is still full price at $79</a>, but REI members can get rewards. <a class="view-deal button" href="https://www.rei.com/product/242671/patagonia-micro-d-half-zip-fleece-pullover-womens" target="_blank" rel="nofollow" data-dimension112="5739cefc-cf13-11f1-bae6-3b754de32af0" data-action="Deal Block" data-label="Micro-D Half-Zip Fleece Pullover (Women's)" data-dimension48="Micro-D Half-Zip Fleece Pullover (Women's)" data-dimension25="$48">View Deal</a></p></div><div class="product"><a data-dimension112="5739cf56-cf13-11f1-8ab2-a5e2fc3975b6" data-action="Deal Block" data-label="Baggies Shorts (Men’s)" data-dimension48="Baggies Shorts (Men’s)" data-dimension25="$54" href="https://www.rei.com/product/242831/patagonia-baggies-5-shorts-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1504px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="JtXgyevXrT5SUBGhvhBYQF" name="patagonia baggies" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/JtXgyevXrT5SUBGhvhBYQF-1920-80.jpg" mos="" align="middle" fullscreen="" width="1504" height="1504" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/242831/patagonia-baggies-5-shorts-mens" target="_blank" rel="nofollow" data-dimension112="5739cf56-cf13-11f1-8ab2-a5e2fc3975b6" data-action="Deal Block" data-label="Baggies Shorts (Men’s)" data-dimension48="Baggies Shorts (Men’s)" data-dimension25="$54">Baggies Shorts (Men’s): was $69 now $54</a></strong><br />Summer may be long gone, but Patagonia's Baggie shorts are suitable for both inside and out of the water. And as the brand clears out its end-of-season styles, you can get these shorts for as low as $54.<a class="view-deal button" href="https://www.rei.com/product/242831/patagonia-baggies-5-shorts-mens" target="_blank" rel="nofollow" data-dimension112="5739cf56-cf13-11f1-8ab2-a5e2fc3975b6" data-action="Deal Block" data-label="Baggies Shorts (Men’s)" data-dimension48="Baggies Shorts (Men’s)" data-dimension25="$54">View Deal</a></p></div><div class="product"><a data-dimension112="5739cfba-cf13-11f1-aa7a-c5c42a5782ea" data-action="Deal Block" data-label="Outdoor Everyday Pants (Women's)" data-dimension48="Outdoor Everyday Pants (Women's)" data-dimension25="$68" href="https://www.rei.com/product/228412/patagonia-outdoor-everyday-pants-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="zoeCcCwPahdqAedoN2ztbX" name="pants" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zoeCcCwPahdqAedoN2ztbX-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/228412/patagonia-outdoor-everyday-pants-womens" target="_blank" rel="nofollow" data-dimension112="5739cfba-cf13-11f1-aa7a-c5c42a5782ea" data-action="Deal Block" data-label="Outdoor Everyday Pants (Women's)" data-dimension48="Outdoor Everyday Pants (Women's)" data-dimension25="$68">Outdoor Everyday Pants (Women's): was $99 now $68</a></strong><br />Although they look like sweatpants, the Patagonia Outdoor Everyday Pants are ideal for hikes and outdoor activities. As they're wide-legged, they're super comfortable, and are even water-repellant. They're on sale in two different colors.<a class="view-deal button" href="https://www.rei.com/product/228412/patagonia-outdoor-everyday-pants-womens" target="_blank" rel="nofollow" data-dimension112="5739cfba-cf13-11f1-aa7a-c5c42a5782ea" data-action="Deal Block" data-label="Outdoor Everyday Pants (Women's)" data-dimension48="Outdoor Everyday Pants (Women's)" data-dimension25="$68">View Deal</a></p></div><div class="product"><a data-dimension112="5739d01e-cf13-11f1-b67b-a7f8d31541ed" data-action="Deal Block" data-label="P-6 Logo Uprisal Hoody (Unisex)" data-dimension48="P-6 Logo Uprisal Hoody (Unisex)" data-dimension25="$71" href="https://www.rei.com/product/191626/patagonia-p-6-logo-uprisal-hoody" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1707px;"><p class="vanilla-image-block" style="padding-top:117.16%;"><img id="AxhSkgAYP5VCo4UWcfgBNi" name="Patagonia hoodie" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/AxhSkgAYP5VCo4UWcfgBNi-1920-80.jpg" mos="" align="middle" fullscreen="" width="1707" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/191626/patagonia-p-6-logo-uprisal-hoody" target="_blank" rel="nofollow" data-dimension112="5739d01e-cf13-11f1-b67b-a7f8d31541ed" data-action="Deal Block" data-label="P-6 Logo Uprisal Hoody (Unisex)" data-dimension48="P-6 Logo Uprisal Hoody (Unisex)" data-dimension25="$71">P-6 Logo Uprisal Hoody (Unisex): was $95 now $71</a></strong><br />This is such a classic versatile hoody, I can't quite believe it's discounted in three colors. This is the kind of sweater that never goes out of style. This hoody is made from 30 plastic bottles, so you know you're wearing something that is benefitting the planet.  <a class="view-deal button" href="https://www.rei.com/product/191626/patagonia-p-6-logo-uprisal-hoody" target="_blank" rel="nofollow" data-dimension112="5739d01e-cf13-11f1-b67b-a7f8d31541ed" data-action="Deal Block" data-label="P-6 Logo Uprisal Hoody (Unisex)" data-dimension48="P-6 Logo Uprisal Hoody (Unisex)" data-dimension25="$71">View Deal</a></p></div><div class="product"><a data-dimension112="5739d0d2-cf13-11f1-a651-8f12914c5637" data-action="Deal Block" data-label="Black Hole Pack 25L" data-dimension48="Black Hole Pack 25L" data-dimension25="$76" href="https://www.rei.com/product/221915/patagonia-black-hole-pack-25-l" 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="Ajyo94pRBxZGziA2SbfTtP" name="patagonia black hole yellow" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Ajyo94pRBxZGziA2SbfTtP-1920-80.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/221915/patagonia-black-hole-pack-25-l" target="_blank" rel="nofollow" data-dimension112="5739d0d2-cf13-11f1-a651-8f12914c5637" data-action="Deal Block" data-label="Black Hole Pack 25L" data-dimension48="Black Hole Pack 25L" data-dimension25="$76">Black Hole Pack 25L: was $149 now $76</a></strong><br />The Black Hole Pack is Patagonia's iconic backpack for a reason. This backpack does what it says on the tin — it fits way more stuff than you'd expect. It's on sale for just $76 right now, which is a massive $73 off. Only one color is discounted now, so I'd be quick if you're on the fence. <a class="view-deal button" href="https://www.rei.com/product/221915/patagonia-black-hole-pack-25-l" target="_blank" rel="nofollow" data-dimension112="5739d0d2-cf13-11f1-a651-8f12914c5637" data-action="Deal Block" data-label="Black Hole Pack 25L" data-dimension48="Black Hole Pack 25L" data-dimension25="$76">View Deal</a></p></div><div class="product"><a data-dimension112="5739d12c-cf13-11f1-a5c6-fb7b9b7d41d1" data-action="Deal Block" data-label="Houdini Jacket (Men's)" data-dimension48="Houdini Jacket (Men's)" data-dimension25="$82" href="https://www.rei.com/product/143470/patagonia-houdini-jacket-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:588px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="8GQeT4DV45yR8hUW8QhMEC" name="REI Patagonia jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/8GQeT4DV45yR8hUW8QhMEC-1920-80.jpg" mos="" align="middle" fullscreen="" width="588" height="588" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/143470/patagonia-houdini-jacket-mens" target="_blank" rel="nofollow" data-dimension112="5739d12c-cf13-11f1-a5c6-fb7b9b7d41d1" data-action="Deal Block" data-label="Houdini Jacket (Men's)" data-dimension48="Houdini Jacket (Men's)" data-dimension25="$82">Houdini Jacket (Men's): was $109 now $82</a></strong><br />Lightweight and compact enough to stuff into a back pocket, yet warm and weather-resistant enough to keep you dry and comfy in moderate rain and chilliness, the Patagonia Houdini really lives up to its magical name.  <a class="view-deal button" href="https://www.rei.com/product/143470/patagonia-houdini-jacket-mens" target="_blank" rel="nofollow" data-dimension112="5739d12c-cf13-11f1-a5c6-fb7b9b7d41d1" data-action="Deal Block" data-label="Houdini Jacket (Men's)" data-dimension48="Houdini Jacket (Men's)" data-dimension25="$82">View Deal</a></p></div><div class="product"><a data-dimension112="5739d190-cf13-11f1-8edf-658df9c91b15" data-action="Deal Block" data-label="Snap-T Fleece Pullover" data-dimension48="Snap-T Fleece Pullover" data-dimension25="$82" href="https://www.rei.com/product/252162/patagonia-lightweight-synchilla-snap-t-fleece-pullover-mens?color=ELLWOOD%2520GREEN" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:932px;"><p class="vanilla-image-block" style="padding-top:102.25%;"><img id="3pubarQgzemrCrjiaDFxVf" name="Screenshot 2026-06-15 at 9.10.50 PM" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3pubarQgzemrCrjiaDFxVf-1920-80.png" mos="" align="middle" fullscreen="" width="932" height="953" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/252162/patagonia-lightweight-synchilla-snap-t-fleece-pullover-mens?color=ELLWOOD%2520GREEN" target="_blank" rel="nofollow" data-dimension112="5739d190-cf13-11f1-8edf-658df9c91b15" data-action="Deal Block" data-label="Snap-T Fleece Pullover" data-dimension48="Snap-T Fleece Pullover" data-dimension25="$82">Snap-T Fleece Pullover: was $139 now $82</a></strong><br />Every wardrobe should have one of these classic fleece pullovers. With two stylish colorways to choose from and plenty of sizes still available, the Patagonia Synchilla Snap-T Fleece is the ultimate lounge-around-the-house garment for cooler temps. <a class="view-deal button" href="https://www.rei.com/product/252162/patagonia-lightweight-synchilla-snap-t-fleece-pullover-mens?color=ELLWOOD%2520GREEN" target="_blank" rel="nofollow" data-dimension112="5739d190-cf13-11f1-8edf-658df9c91b15" data-action="Deal Block" data-label="Snap-T Fleece Pullover" data-dimension48="Snap-T Fleece Pullover" data-dimension25="$82">View Deal</a></p></div><div class="product"><a data-dimension112="5739d1ea-cf13-11f1-8038-3d9c96b33bf6" data-action="Deal Block" data-label="Ahnya Pullover (Women's)" data-dimension48="Ahnya Pullover (Women's)" data-dimension25="$93" href="https://www.rei.com/product/250042/patagonia-ahnya-full-zip-hoody-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1600px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="8Ja4UguKzZauzQ2r3qNtGm" name="patagonia" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/8Ja4UguKzZauzQ2r3qNtGm-1920-80.jpg" mos="" align="middle" fullscreen="" width="1600" height="1600" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/250042/patagonia-ahnya-full-zip-hoody-womens" target="_blank" rel="nofollow" data-dimension112="5739d1ea-cf13-11f1-8038-3d9c96b33bf6" data-action="Deal Block" data-label="Ahnya Pullover (Women's)" data-dimension48="Ahnya Pullover (Women's)" data-dimension25="$93">Ahnya Pullover (Women's): was $135 now $93</a></strong><br />Nothing says fall apparel like a lightweight pullover. The sweatshirt is made with Regenerative Organic Certified cotton and recycled polyester fleece and spandex, with front pockets and rib-knit cuffs. It's perfect for throwing over a tee or wearing under a jacket.<a class="view-deal button" href="https://www.rei.com/product/250042/patagonia-ahnya-full-zip-hoody-womens" target="_blank" rel="nofollow" data-dimension112="5739d1ea-cf13-11f1-8038-3d9c96b33bf6" data-action="Deal Block" data-label="Ahnya Pullover (Women's)" data-dimension48="Ahnya Pullover (Women's)" data-dimension25="$93">View Deal</a></p></div><div class="product"><a data-dimension112="5739d276-cf13-11f1-ab19-a39159ec7544" data-action="Deal Block" data-label="Houdini Half-zip" data-dimension48="Houdini Half-zip" data-dimension25="$100" href="https://www.rei.com/product/228564/patagonia-houdini-stash-half-zip-jacket-mens?color=CASCADE%2520GREEN" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1090px;"><p class="vanilla-image-block" style="padding-top:112.75%;"><img id="Ae9C3N28VXVi824kshL69a" name="Screenshot 2026-06-15 at 9.10.35 PM" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Ae9C3N28VXVi824kshL69a-1920-80.png" mos="" align="middle" fullscreen="" width="1090" height="1229" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Patagonia Houdini Half-Zip is nothing short of pure magic. This back-pocket-packable pull-over weighs about as much as a deck of playing cards, yet offers seriously solid protection from the rain, wind and chill.<a class="view-deal button" href="https://www.rei.com/product/228564/patagonia-houdini-stash-half-zip-jacket-mens?color=CASCADE%2520GREEN" target="_blank" rel="nofollow" data-dimension112="5739d276-cf13-11f1-ab19-a39159ec7544" data-action="Deal Block" data-label="Houdini Half-zip" data-dimension48="Houdini Half-zip" data-dimension25="$100">View Deal</a></p></div><div class="product"><a data-dimension112="5739d2d0-cf13-11f1-921f-bd7957933c9f" data-action="Deal Block" data-label="R1 Pullover - Women's" data-dimension48="R1 Pullover - Women's" data-dimension25="$107" href="https://www.rei.com/product/242323/patagonia-r1-pullover-womens" 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="bre5ZuSFLvwfm5qxrkvwTm" name="patagonia r1 pullover" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bre5ZuSFLvwfm5qxrkvwTm-1920-80.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/242323/patagonia-r1-pullover-womens" target="_blank" rel="nofollow" data-dimension112="5739d2d0-cf13-11f1-921f-bd7957933c9f" data-action="Deal Block" data-label="R1 Pullover - Women's" data-dimension48="R1 Pullover - Women's" data-dimension25="$107">R1 Pullover - Women's: was $155 now $107</a></strong><br />The Patagonia R1 Pullover is a midlayer, meaning it's intended to be worn between a thermal base layer and an outer waterproof or windproof jacket like the Patagonia Houdini. <a class="view-deal button" href="https://www.rei.com/product/242323/patagonia-r1-pullover-womens" target="_blank" rel="nofollow" data-dimension112="5739d2d0-cf13-11f1-921f-bd7957933c9f" data-action="Deal Block" data-label="R1 Pullover - Women's" data-dimension48="R1 Pullover - Women's" data-dimension25="$107">View Deal</a></p></div><div class="product"><a data-dimension112="5739d334-cf13-11f1-95a9-756182c4d48a" data-action="Deal Block" data-label="Daily Snap-T Pullover - Women's" data-dimension48="Daily Snap-T Pullover - Women's" data-dimension25="$109" href="https://www.rei.com/product/C12816/patagonia-daily-snap-t-pullover-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1664px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="So92hKGkLN6sjJXpmCtawA" name="patagonia snap-t daily pullover" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/So92hKGkLN6sjJXpmCtawA-1920-80.jpg" mos="" align="middle" fullscreen="" width="1664" height="1664" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C12816/patagonia-daily-snap-t-pullover-womens" target="_blank" rel="nofollow" data-dimension112="5739d334-cf13-11f1-95a9-756182c4d48a" data-action="Deal Block" data-label="Daily Snap-T Pullover - Women's" data-dimension48="Daily Snap-T Pullover - Women's" data-dimension25="$109">Daily Snap-T Pullover - Women's: was $169 now $109</a></strong><br />This fleece is perfect to wear at the campsite during chilly evenings, or on early morning trails. The Daily Snap-T Pullover is made from 100% regenerative organic cotton as well.<a class="view-deal button" href="https://www.rei.com/product/C12816/patagonia-daily-snap-t-pullover-womens" target="_blank" rel="nofollow" data-dimension112="5739d334-cf13-11f1-95a9-756182c4d48a" data-action="Deal Block" data-label="Daily Snap-T Pullover - Women's" data-dimension48="Daily Snap-T Pullover - Women's" data-dimension25="$109">View Deal</a></p></div><div class="product"><a data-dimension112="5739d38e-cf13-11f1-b911-d5fb61715add" data-action="Deal Block" data-label="Daily Snap-T Pullover (Men's)" data-dimension48="Daily Snap-T Pullover (Men's)" data-dimension25="$124" href="https://www.rei.com/product/C01345/patagonia-daily-snap-t-pullover-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1560px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="WGXNCXSCXiBba8uzoeFYnS" name="Patagonia Snap T" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/WGXNCXSCXiBba8uzoeFYnS-1920-80.jpg" mos="" align="middle" fullscreen="" width="1560" height="1560" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01345/patagonia-daily-snap-t-pullover-mens" target="_blank" rel="nofollow" data-dimension112="5739d38e-cf13-11f1-b911-d5fb61715add" data-action="Deal Block" data-label="Daily Snap-T Pullover (Men's)" data-dimension48="Daily Snap-T Pullover (Men's)" data-dimension25="$124">Daily Snap-T Pullover (Men's): was $179 now $124</a></strong><br />This is the same as the deal listed above, except it's the men's version. It's available in nearly every single size in three different colors, so you'll be able to find your perfect fit. <a class="view-deal button" href="https://www.rei.com/product/C01345/patagonia-daily-snap-t-pullover-mens" target="_blank" rel="nofollow" data-dimension112="5739d38e-cf13-11f1-b911-d5fb61715add" data-action="Deal Block" data-label="Daily Snap-T Pullover (Men's)" data-dimension48="Daily Snap-T Pullover (Men's)" data-dimension25="$124">View Deal</a></p></div><div class="product"><a data-dimension112="5739d3f2-cf13-11f1-8c61-9da4a4ad59f0" data-action="Deal Block" data-label="Nano-Air Ultralight Hoody (Women's)" data-dimension48="Nano-Air Ultralight Hoody (Women's)" data-dimension25="$161" href="https://www.rei.com/product/C09325/patagonia-nano-air-ultralight-full-zip-hoody-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1608px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="PqgeChqQKgNDQGpRCoXDEh" name="Patagonia deals" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/PqgeChqQKgNDQGpRCoXDEh-1920-80.jpg" mos="" align="middle" fullscreen="" width="1608" height="1608" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C09325/patagonia-nano-air-ultralight-full-zip-hoody-womens" target="_blank" rel="nofollow" data-dimension112="5739d3f2-cf13-11f1-8c61-9da4a4ad59f0" data-action="Deal Block" data-label="Nano-Air Ultralight Hoody (Women's)" data-dimension48="Nano-Air Ultralight Hoody (Women's)" data-dimension25="$161">Nano-Air Ultralight Hoody (Women's): was $249 now $161</a></strong><br />The Nano-Air Ultralight is one of the <a href="https://www.tomsguide.com/wellness/fitness/patagonia-nano-air-ultralight-review-outrageous-comfort-doesnt-come-cheap">best jackets we’ve ever tested </a>and a go-to in our Fitness Writer's daily rotation thanks to its use of super-soft and breathable materials with easy-roll-up sleeves and a comfortable, slightly fitted design. It’s also rarely on sale for as much as 35% off. <a class="view-deal button" href="https://www.rei.com/product/C09325/patagonia-nano-air-ultralight-full-zip-hoody-womens" target="_blank" rel="nofollow" data-dimension112="5739d3f2-cf13-11f1-8c61-9da4a4ad59f0" data-action="Deal Block" data-label="Nano-Air Ultralight Hoody (Women's)" data-dimension48="Nano-Air Ultralight Hoody (Women's)" data-dimension25="$161">View Deal</a></p></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness/15-best-patagonia-deals-at-rei-save-up-to-50-percent-on-my-favorite-fall-finds</link>
                                                                            <description>
                            <![CDATA[ REI just slashed prices on Patagonia gear. Save up to 50% on my favorite fall styles. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">m8M9EYXqERYR3VNRRSAjXH</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/YcxLyCtwMkoWmrjSGrLKcV-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 26 Oct 2026 08:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Fitness]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Olivia Halevy ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/YAg7Fmh9dGKbg3hULBMWiU-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Olivia is a Deals Writer at Tom’s Guide. She loves all things lifestyle, shopping and sourcing the best deals from some of the top brands, retailers and websites around. From fashion and beauty to smart home and tech, she has an eye for finding practical, stylish, and reasonably-priced items that help make life simpler (and a little more aesthetically-pleasing).&amp;nbsp;Olivia has over five years of experience writing lifestyle, commerce, and branded content for &lt;a href=&quot;http://patch.com/&quot;&gt;Patch.com&lt;/a&gt;. She&#039;s covered major shopping holidays like Amazon Prime Day, Black Friday and Cyber Monday. In her free time, she enjoys trying out new exercise classes, binge-watching the latest viral TV shows, cooking, spending time with family and taking long walks with her dog, Gus.&amp;nbsp;&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/YcxLyCtwMkoWmrjSGrLKcV-1920-80.jpg">
                                                            <media:credit><![CDATA[REI / edited by Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[REI deals]]></media:description>                                                            <media:text><![CDATA[REI deals]]></media:text>
                                <media:title type="plain"><![CDATA[REI deals]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/YcxLyCtwMkoWmrjSGrLKcV-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>REI is notorious for offering impressive markdowns on the best outdoor brands — and Patagonia is no exception. Now that temperatures are starting to drop, investing in some high-quality outerwear is a must. And fortunately, <a href="https://www.rei.com/b/patagonia/f/scd-deals?" target="_blank" rel="nofollow">Patagonia's best-selling styles are up to 50% off</a>. </p><p>For instance, <a href="https://www.rei.com/product/143470/patagonia-houdini-jacket-mens" target="_blank" rel="nofollow">the popular Patagonia Houdini Jacket is down to just $82</a> and is the perfect layer for fall adventures. You can also grab <a href="https://www.rei.com/product/242671/patagonia-micro-d-half-zip-fleece-pullover-womens" target="_blank" rel="nofollow">the Patagonia Micro-D Half-Zip Fleece Pullover for just $44</a>. Plus, there's plenty more deals on rain jackets, hats, hoodies and fleeces from $21.</p><p>Patagonia doesn't come cheap, so you'll want to snap up these deals ASAP.  Below, I've rounded up my favorite REI styles. Keep scrolling to check out the deals that are actually worth shopping for fall. </p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><a href="https://www.rei.com/f/scd-deals" target="_blank" rel="nofollow"><strong>shop REI's fall sale</strong></a></li><li><strong>Patagonia: </strong><a href="https://www.rei.com/b/patagonia/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;r=f%3Bb&amp;sort=min-price" target="_blank" rel="nofollow"><strong>apparel/accessories from $15</strong></a></li><li><strong>Camping gear: </strong><a href="https://www.rei.com/c/camping-and-hiking/f/scd-deals" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li><li><strong>Vuori: </strong><a href="https://www.rei.com/b/vuori/f/scd-deals?" target="_blank" rel="nofollow"><strong>up to 40% off</strong></a></li><li><strong>Arc'teryx: </strong><a href="https://www.rei.com/b/arcteryx/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;sort=min-price&amp;r=f%3Bb" target="_blank" rel="nofollow"><strong>apparel from $24</strong></a></li><li><strong>Columbia: </strong><a href="https://www.rei.com/b/columbia/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;sort=min-price&amp;irclickid=3KjxOUTuLxyKWYwT3BUaGy3DUkp2c0Uto0pyw40" target="_blank" rel="nofollow"><strong>apparel from $14</strong></a></li><li><strong>Marmot: </strong><a href="https://www.rei.com/b/marmot/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;sort=min-price&amp;r=f%3Bb" target="_blank" rel="nofollow"><strong>apparel from $15</strong></a></li><li><strong>The North Face: </strong><a href="https://www.rei.com/b/the-north-face/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;r=f%3Bb&amp;sort=min-price" target="_blank" rel="nofollow"><strong>apparel from $16</strong></a></li><li><strong>Yeti: </strong><a href="https://www.rei.com/b/yeti/f/scd-deals?" target="_blank" rel="nofollow"><strong>water bottles from $17</strong></a></li><li><strong>Saucony: </strong><a href="https://www.rei.com/b/saucony/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;sort=min-price&amp;r=f%3Bb" target="_blank" rel="nofollow"><strong>running gear from $46</strong></a><strong></strong></li></ul><h3 class="article-body__section" id="section-top-patagonia-deals"><span>Top Patagonia Deals</span></h3><div class="product"><a data-dimension112="5739ce20-cf13-11f1-a7ce-574d3763f097" data-action="Deal Block" data-label="Coastal Cable Beanie" data-dimension48="Coastal Cable Beanie" data-dimension25="$21" href="https://www.rei.com/product/240304/patagonia-coastal-cable-beanie" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:932px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="aBHmT9EnHGHJTKCk7hooyT" name="patagonia coastal cable beanie" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/aBHmT9EnHGHJTKCk7hooyT-1920-80.jpg" mos="" align="middle" fullscreen="" width="932" height="932" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>Made with recycled wool and recycled nylon, the Patagonia Coastal Cable beanie is super-warm and super-fuzzy, perfect for winter and fall. There's even a recycled fleece headband to keep the cold out and the warm in. The green color is eye-catching enough to ensure your friends will never lose you on the slopes or in the city. <a class="view-deal button" href="https://www.rei.com/product/240304/patagonia-coastal-cable-beanie" target="_blank" rel="nofollow" data-dimension112="5739ce20-cf13-11f1-a7ce-574d3763f097" data-action="Deal Block" data-label="Coastal Cable Beanie" data-dimension48="Coastal Cable Beanie" data-dimension25="$21">View Deal</a></p></div><div class="product"><a data-dimension112="5739ce8e-cf13-11f1-8e1c-5335e032695f" data-action="Deal Block" data-label="Powder Town Headband" data-dimension48="Powder Town Headband" data-dimension25="$22" href="https://www.rei.com/product/240312/patagonia-powder-town-headband" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:932px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="ekwiWeSPvjXJ3G4PTtqQXP" name="patagonia powder town headband" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ekwiWeSPvjXJ3G4PTtqQXP-1920-80.jpg" mos="" align="middle" fullscreen="" width="932" height="932" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Patagonia Powder Town Headband is designed to keep your ears warm on the slopes, without overheating the rest of you. It's also so bright that your friends will always be able to find you. This headband has a moisture-wicking recycled fleece lining to keep you dry and cozy. <a class="view-deal button" href="https://www.rei.com/product/240312/patagonia-powder-town-headband" target="_blank" rel="nofollow" data-dimension112="5739ce8e-cf13-11f1-8e1c-5335e032695f" data-action="Deal Block" data-label="Powder Town Headband" data-dimension48="Powder Town Headband" data-dimension25="$22">View Deal</a></p></div><div class="product"><a data-dimension112="5739cefc-cf13-11f1-bae6-3b754de32af0" data-action="Deal Block" data-label="Micro-D Half-Zip Fleece Pullover (Women's)" data-dimension48="Micro-D Half-Zip Fleece Pullover (Women's)" data-dimension25="$48" href="https://www.rei.com/product/242671/patagonia-micro-d-half-zip-fleece-pullover-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1576px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="nf39PweshXkywy2qiMnC8k" name="b28afb8f-ec50-4921-9346-b3269d66e19b" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/nf39PweshXkywy2qiMnC8k-1920-80.jpg" mos="" align="middle" fullscreen="" width="1576" height="1576" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/242671/patagonia-micro-d-half-zip-fleece-pullover-womens" target="_blank" rel="nofollow" data-dimension112="5739cefc-cf13-11f1-bae6-3b754de32af0" data-action="Deal Block" data-label="Micro-D Half-Zip Fleece Pullover (Women's)" data-dimension48="Micro-D Half-Zip Fleece Pullover (Women's)" data-dimension25="$48">Micro-D Half-Zip Fleece Pullover (Women's): was $99 now $48</a></strong><br />Right now, the beautiful Thin Ice colorway is down to $48 in REI’s mid-season deal. It’s still available in a handful of sizes. The <a href="https://www.rei.com/product/143319/patagonia-micro-d-fleece-pullover-mens%20" target="_blank" rel="nofollow">men’s Micro D Fleece Pullover is still full price at $79</a>, but REI members can get rewards. <a class="view-deal button" href="https://www.rei.com/product/242671/patagonia-micro-d-half-zip-fleece-pullover-womens" target="_blank" rel="nofollow" data-dimension112="5739cefc-cf13-11f1-bae6-3b754de32af0" data-action="Deal Block" data-label="Micro-D Half-Zip Fleece Pullover (Women's)" data-dimension48="Micro-D Half-Zip Fleece Pullover (Women's)" data-dimension25="$48">View Deal</a></p></div><div class="product"><a data-dimension112="5739cf56-cf13-11f1-8ab2-a5e2fc3975b6" data-action="Deal Block" data-label="Baggies Shorts (Men’s)" data-dimension48="Baggies Shorts (Men’s)" data-dimension25="$54" href="https://www.rei.com/product/242831/patagonia-baggies-5-shorts-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1504px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="JtXgyevXrT5SUBGhvhBYQF" name="patagonia baggies" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/JtXgyevXrT5SUBGhvhBYQF-1920-80.jpg" mos="" align="middle" fullscreen="" width="1504" height="1504" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/242831/patagonia-baggies-5-shorts-mens" target="_blank" rel="nofollow" data-dimension112="5739cf56-cf13-11f1-8ab2-a5e2fc3975b6" data-action="Deal Block" data-label="Baggies Shorts (Men’s)" data-dimension48="Baggies Shorts (Men’s)" data-dimension25="$54">Baggies Shorts (Men’s): was $69 now $54</a></strong><br />Summer may be long gone, but Patagonia's Baggie shorts are suitable for both inside and out of the water. And as the brand clears out its end-of-season styles, you can get these shorts for as low as $54.<a class="view-deal button" href="https://www.rei.com/product/242831/patagonia-baggies-5-shorts-mens" target="_blank" rel="nofollow" data-dimension112="5739cf56-cf13-11f1-8ab2-a5e2fc3975b6" data-action="Deal Block" data-label="Baggies Shorts (Men’s)" data-dimension48="Baggies Shorts (Men’s)" data-dimension25="$54">View Deal</a></p></div><div class="product"><a data-dimension112="5739cfba-cf13-11f1-aa7a-c5c42a5782ea" data-action="Deal Block" data-label="Outdoor Everyday Pants (Women's)" data-dimension48="Outdoor Everyday Pants (Women's)" data-dimension25="$68" href="https://www.rei.com/product/228412/patagonia-outdoor-everyday-pants-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="zoeCcCwPahdqAedoN2ztbX" name="pants" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zoeCcCwPahdqAedoN2ztbX-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/228412/patagonia-outdoor-everyday-pants-womens" target="_blank" rel="nofollow" data-dimension112="5739cfba-cf13-11f1-aa7a-c5c42a5782ea" data-action="Deal Block" data-label="Outdoor Everyday Pants (Women's)" data-dimension48="Outdoor Everyday Pants (Women's)" data-dimension25="$68">Outdoor Everyday Pants (Women's): was $99 now $68</a></strong><br />Although they look like sweatpants, the Patagonia Outdoor Everyday Pants are ideal for hikes and outdoor activities. As they're wide-legged, they're super comfortable, and are even water-repellant. They're on sale in two different colors.<a class="view-deal button" href="https://www.rei.com/product/228412/patagonia-outdoor-everyday-pants-womens" target="_blank" rel="nofollow" data-dimension112="5739cfba-cf13-11f1-aa7a-c5c42a5782ea" data-action="Deal Block" data-label="Outdoor Everyday Pants (Women's)" data-dimension48="Outdoor Everyday Pants (Women's)" data-dimension25="$68">View Deal</a></p></div><div class="product"><a data-dimension112="5739d01e-cf13-11f1-b67b-a7f8d31541ed" data-action="Deal Block" data-label="P-6 Logo Uprisal Hoody (Unisex)" data-dimension48="P-6 Logo Uprisal Hoody (Unisex)" data-dimension25="$71" href="https://www.rei.com/product/191626/patagonia-p-6-logo-uprisal-hoody" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1707px;"><p class="vanilla-image-block" style="padding-top:117.16%;"><img id="AxhSkgAYP5VCo4UWcfgBNi" name="Patagonia hoodie" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/AxhSkgAYP5VCo4UWcfgBNi-1920-80.jpg" mos="" align="middle" fullscreen="" width="1707" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/191626/patagonia-p-6-logo-uprisal-hoody" target="_blank" rel="nofollow" data-dimension112="5739d01e-cf13-11f1-b67b-a7f8d31541ed" data-action="Deal Block" data-label="P-6 Logo Uprisal Hoody (Unisex)" data-dimension48="P-6 Logo Uprisal Hoody (Unisex)" data-dimension25="$71">P-6 Logo Uprisal Hoody (Unisex): was $95 now $71</a></strong><br />This is such a classic versatile hoody, I can't quite believe it's discounted in three colors. This is the kind of sweater that never goes out of style. This hoody is made from 30 plastic bottles, so you know you're wearing something that is benefitting the planet.  <a class="view-deal button" href="https://www.rei.com/product/191626/patagonia-p-6-logo-uprisal-hoody" target="_blank" rel="nofollow" data-dimension112="5739d01e-cf13-11f1-b67b-a7f8d31541ed" data-action="Deal Block" data-label="P-6 Logo Uprisal Hoody (Unisex)" data-dimension48="P-6 Logo Uprisal Hoody (Unisex)" data-dimension25="$71">View Deal</a></p></div><div class="product"><a data-dimension112="5739d0d2-cf13-11f1-a651-8f12914c5637" data-action="Deal Block" data-label="Black Hole Pack 25L" data-dimension48="Black Hole Pack 25L" data-dimension25="$76" href="https://www.rei.com/product/221915/patagonia-black-hole-pack-25-l" 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="Ajyo94pRBxZGziA2SbfTtP" name="patagonia black hole yellow" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Ajyo94pRBxZGziA2SbfTtP-1920-80.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/221915/patagonia-black-hole-pack-25-l" target="_blank" rel="nofollow" data-dimension112="5739d0d2-cf13-11f1-a651-8f12914c5637" data-action="Deal Block" data-label="Black Hole Pack 25L" data-dimension48="Black Hole Pack 25L" data-dimension25="$76">Black Hole Pack 25L: was $149 now $76</a></strong><br />The Black Hole Pack is Patagonia's iconic backpack for a reason. This backpack does what it says on the tin — it fits way more stuff than you'd expect. It's on sale for just $76 right now, which is a massive $73 off. Only one color is discounted now, so I'd be quick if you're on the fence. <a class="view-deal button" href="https://www.rei.com/product/221915/patagonia-black-hole-pack-25-l" target="_blank" rel="nofollow" data-dimension112="5739d0d2-cf13-11f1-a651-8f12914c5637" data-action="Deal Block" data-label="Black Hole Pack 25L" data-dimension48="Black Hole Pack 25L" data-dimension25="$76">View Deal</a></p></div><div class="product"><a data-dimension112="5739d12c-cf13-11f1-a5c6-fb7b9b7d41d1" data-action="Deal Block" data-label="Houdini Jacket (Men's)" data-dimension48="Houdini Jacket (Men's)" data-dimension25="$82" href="https://www.rei.com/product/143470/patagonia-houdini-jacket-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:588px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="8GQeT4DV45yR8hUW8QhMEC" name="REI Patagonia jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/8GQeT4DV45yR8hUW8QhMEC-1920-80.jpg" mos="" align="middle" fullscreen="" width="588" height="588" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/143470/patagonia-houdini-jacket-mens" target="_blank" rel="nofollow" data-dimension112="5739d12c-cf13-11f1-a5c6-fb7b9b7d41d1" data-action="Deal Block" data-label="Houdini Jacket (Men's)" data-dimension48="Houdini Jacket (Men's)" data-dimension25="$82">Houdini Jacket (Men's): was $109 now $82</a></strong><br />Lightweight and compact enough to stuff into a back pocket, yet warm and weather-resistant enough to keep you dry and comfy in moderate rain and chilliness, the Patagonia Houdini really lives up to its magical name.  <a class="view-deal button" href="https://www.rei.com/product/143470/patagonia-houdini-jacket-mens" target="_blank" rel="nofollow" data-dimension112="5739d12c-cf13-11f1-a5c6-fb7b9b7d41d1" data-action="Deal Block" data-label="Houdini Jacket (Men's)" data-dimension48="Houdini Jacket (Men's)" data-dimension25="$82">View Deal</a></p></div><div class="product"><a data-dimension112="5739d190-cf13-11f1-8edf-658df9c91b15" data-action="Deal Block" data-label="Snap-T Fleece Pullover" data-dimension48="Snap-T Fleece Pullover" data-dimension25="$82" href="https://www.rei.com/product/252162/patagonia-lightweight-synchilla-snap-t-fleece-pullover-mens?color=ELLWOOD%2520GREEN" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:932px;"><p class="vanilla-image-block" style="padding-top:102.25%;"><img id="3pubarQgzemrCrjiaDFxVf" name="Screenshot 2026-06-15 at 9.10.50 PM" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3pubarQgzemrCrjiaDFxVf-1920-80.png" mos="" align="middle" fullscreen="" width="932" height="953" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/252162/patagonia-lightweight-synchilla-snap-t-fleece-pullover-mens?color=ELLWOOD%2520GREEN" target="_blank" rel="nofollow" data-dimension112="5739d190-cf13-11f1-8edf-658df9c91b15" data-action="Deal Block" data-label="Snap-T Fleece Pullover" data-dimension48="Snap-T Fleece Pullover" data-dimension25="$82">Snap-T Fleece Pullover: was $139 now $82</a></strong><br />Every wardrobe should have one of these classic fleece pullovers. With two stylish colorways to choose from and plenty of sizes still available, the Patagonia Synchilla Snap-T Fleece is the ultimate lounge-around-the-house garment for cooler temps. <a class="view-deal button" href="https://www.rei.com/product/252162/patagonia-lightweight-synchilla-snap-t-fleece-pullover-mens?color=ELLWOOD%2520GREEN" target="_blank" rel="nofollow" data-dimension112="5739d190-cf13-11f1-8edf-658df9c91b15" data-action="Deal Block" data-label="Snap-T Fleece Pullover" data-dimension48="Snap-T Fleece Pullover" data-dimension25="$82">View Deal</a></p></div><div class="product"><a data-dimension112="5739d1ea-cf13-11f1-8038-3d9c96b33bf6" data-action="Deal Block" data-label="Ahnya Pullover (Women's)" data-dimension48="Ahnya Pullover (Women's)" data-dimension25="$93" href="https://www.rei.com/product/250042/patagonia-ahnya-full-zip-hoody-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1600px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="8Ja4UguKzZauzQ2r3qNtGm" name="patagonia" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/8Ja4UguKzZauzQ2r3qNtGm-1920-80.jpg" mos="" align="middle" fullscreen="" width="1600" height="1600" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/250042/patagonia-ahnya-full-zip-hoody-womens" target="_blank" rel="nofollow" data-dimension112="5739d1ea-cf13-11f1-8038-3d9c96b33bf6" data-action="Deal Block" data-label="Ahnya Pullover (Women's)" data-dimension48="Ahnya Pullover (Women's)" data-dimension25="$93">Ahnya Pullover (Women's): was $135 now $93</a></strong><br />Nothing says fall apparel like a lightweight pullover. The sweatshirt is made with Regenerative Organic Certified cotton and recycled polyester fleece and spandex, with front pockets and rib-knit cuffs. It's perfect for throwing over a tee or wearing under a jacket.<a class="view-deal button" href="https://www.rei.com/product/250042/patagonia-ahnya-full-zip-hoody-womens" target="_blank" rel="nofollow" data-dimension112="5739d1ea-cf13-11f1-8038-3d9c96b33bf6" data-action="Deal Block" data-label="Ahnya Pullover (Women's)" data-dimension48="Ahnya Pullover (Women's)" data-dimension25="$93">View Deal</a></p></div><div class="product"><a data-dimension112="5739d276-cf13-11f1-ab19-a39159ec7544" data-action="Deal Block" data-label="Houdini Half-zip" data-dimension48="Houdini Half-zip" data-dimension25="$100" href="https://www.rei.com/product/228564/patagonia-houdini-stash-half-zip-jacket-mens?color=CASCADE%2520GREEN" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1090px;"><p class="vanilla-image-block" style="padding-top:112.75%;"><img id="Ae9C3N28VXVi824kshL69a" name="Screenshot 2026-06-15 at 9.10.35 PM" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Ae9C3N28VXVi824kshL69a-1920-80.png" mos="" align="middle" fullscreen="" width="1090" height="1229" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Patagonia Houdini Half-Zip is nothing short of pure magic. This back-pocket-packable pull-over weighs about as much as a deck of playing cards, yet offers seriously solid protection from the rain, wind and chill.<a class="view-deal button" href="https://www.rei.com/product/228564/patagonia-houdini-stash-half-zip-jacket-mens?color=CASCADE%2520GREEN" target="_blank" rel="nofollow" data-dimension112="5739d276-cf13-11f1-ab19-a39159ec7544" data-action="Deal Block" data-label="Houdini Half-zip" data-dimension48="Houdini Half-zip" data-dimension25="$100">View Deal</a></p></div><div class="product"><a data-dimension112="5739d2d0-cf13-11f1-921f-bd7957933c9f" data-action="Deal Block" data-label="R1 Pullover - Women's" data-dimension48="R1 Pullover - Women's" data-dimension25="$107" href="https://www.rei.com/product/242323/patagonia-r1-pullover-womens" 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="bre5ZuSFLvwfm5qxrkvwTm" name="patagonia r1 pullover" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bre5ZuSFLvwfm5qxrkvwTm-1920-80.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/242323/patagonia-r1-pullover-womens" target="_blank" rel="nofollow" data-dimension112="5739d2d0-cf13-11f1-921f-bd7957933c9f" data-action="Deal Block" data-label="R1 Pullover - Women's" data-dimension48="R1 Pullover - Women's" data-dimension25="$107">R1 Pullover - Women's: was $155 now $107</a></strong><br />The Patagonia R1 Pullover is a midlayer, meaning it's intended to be worn between a thermal base layer and an outer waterproof or windproof jacket like the Patagonia Houdini. <a class="view-deal button" href="https://www.rei.com/product/242323/patagonia-r1-pullover-womens" target="_blank" rel="nofollow" data-dimension112="5739d2d0-cf13-11f1-921f-bd7957933c9f" data-action="Deal Block" data-label="R1 Pullover - Women's" data-dimension48="R1 Pullover - Women's" data-dimension25="$107">View Deal</a></p></div><div class="product"><a data-dimension112="5739d334-cf13-11f1-95a9-756182c4d48a" data-action="Deal Block" data-label="Daily Snap-T Pullover - Women's" data-dimension48="Daily Snap-T Pullover - Women's" data-dimension25="$109" href="https://www.rei.com/product/C12816/patagonia-daily-snap-t-pullover-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1664px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="So92hKGkLN6sjJXpmCtawA" name="patagonia snap-t daily pullover" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/So92hKGkLN6sjJXpmCtawA-1920-80.jpg" mos="" align="middle" fullscreen="" width="1664" height="1664" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C12816/patagonia-daily-snap-t-pullover-womens" target="_blank" rel="nofollow" data-dimension112="5739d334-cf13-11f1-95a9-756182c4d48a" data-action="Deal Block" data-label="Daily Snap-T Pullover - Women's" data-dimension48="Daily Snap-T Pullover - Women's" data-dimension25="$109">Daily Snap-T Pullover - Women's: was $169 now $109</a></strong><br />This fleece is perfect to wear at the campsite during chilly evenings, or on early morning trails. The Daily Snap-T Pullover is made from 100% regenerative organic cotton as well.<a class="view-deal button" href="https://www.rei.com/product/C12816/patagonia-daily-snap-t-pullover-womens" target="_blank" rel="nofollow" data-dimension112="5739d334-cf13-11f1-95a9-756182c4d48a" data-action="Deal Block" data-label="Daily Snap-T Pullover - Women's" data-dimension48="Daily Snap-T Pullover - Women's" data-dimension25="$109">View Deal</a></p></div><div class="product"><a data-dimension112="5739d38e-cf13-11f1-b911-d5fb61715add" data-action="Deal Block" data-label="Daily Snap-T Pullover (Men's)" data-dimension48="Daily Snap-T Pullover (Men's)" data-dimension25="$124" href="https://www.rei.com/product/C01345/patagonia-daily-snap-t-pullover-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1560px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="WGXNCXSCXiBba8uzoeFYnS" name="Patagonia Snap T" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/WGXNCXSCXiBba8uzoeFYnS-1920-80.jpg" mos="" align="middle" fullscreen="" width="1560" height="1560" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01345/patagonia-daily-snap-t-pullover-mens" target="_blank" rel="nofollow" data-dimension112="5739d38e-cf13-11f1-b911-d5fb61715add" data-action="Deal Block" data-label="Daily Snap-T Pullover (Men's)" data-dimension48="Daily Snap-T Pullover (Men's)" data-dimension25="$124">Daily Snap-T Pullover (Men's): was $179 now $124</a></strong><br />This is the same as the deal listed above, except it's the men's version. It's available in nearly every single size in three different colors, so you'll be able to find your perfect fit. <a class="view-deal button" href="https://www.rei.com/product/C01345/patagonia-daily-snap-t-pullover-mens" target="_blank" rel="nofollow" data-dimension112="5739d38e-cf13-11f1-b911-d5fb61715add" data-action="Deal Block" data-label="Daily Snap-T Pullover (Men's)" data-dimension48="Daily Snap-T Pullover (Men's)" data-dimension25="$124">View Deal</a></p></div><div class="product"><a data-dimension112="5739d3f2-cf13-11f1-8c61-9da4a4ad59f0" data-action="Deal Block" data-label="Nano-Air Ultralight Hoody (Women's)" data-dimension48="Nano-Air Ultralight Hoody (Women's)" data-dimension25="$161" href="https://www.rei.com/product/C09325/patagonia-nano-air-ultralight-full-zip-hoody-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1608px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="PqgeChqQKgNDQGpRCoXDEh" name="Patagonia deals" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/PqgeChqQKgNDQGpRCoXDEh-1920-80.jpg" mos="" align="middle" fullscreen="" width="1608" height="1608" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C09325/patagonia-nano-air-ultralight-full-zip-hoody-womens" target="_blank" rel="nofollow" data-dimension112="5739d3f2-cf13-11f1-8c61-9da4a4ad59f0" data-action="Deal Block" data-label="Nano-Air Ultralight Hoody (Women's)" data-dimension48="Nano-Air Ultralight Hoody (Women's)" data-dimension25="$161">Nano-Air Ultralight Hoody (Women's): was $249 now $161</a></strong><br />The Nano-Air Ultralight is one of the <a href="https://www.tomsguide.com/wellness/fitness/patagonia-nano-air-ultralight-review-outrageous-comfort-doesnt-come-cheap">best jackets we’ve ever tested </a>and a go-to in our Fitness Writer's daily rotation thanks to its use of super-soft and breathable materials with easy-roll-up sleeves and a comfortable, slightly fitted design. It’s also rarely on sale for as much as 35% off. <a class="view-deal button" href="https://www.rei.com/product/C09325/patagonia-nano-air-ultralight-full-zip-hoody-womens" target="_blank" rel="nofollow" data-dimension112="5739d3f2-cf13-11f1-8c61-9da4a4ad59f0" data-action="Deal Block" data-label="Nano-Air Ultralight Hoody (Women's)" data-dimension48="Nano-Air Ultralight Hoody (Women's)" data-dimension25="$161">View Deal</a></p></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ No, not Pilates — when my lower back aches from sitting all day, this is the 10-minute floor routine I use for relief ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Despite my part-time job as a personal trainer, my full-time work as a fitness editor means I spend quite a lot of time sitting during the day. Sure, I like to get up and move around often, work out, and my dog gets plenty of long walks, but that doesn't always <a href="https://www.tomsguide.com/wellness/workouts/a-top-pilates-instructor-says-these-anti-desk-exercises-are-the-best-thing-you-can-do-to-counter-the-effects-of-sitting-at-any-age">counteract the effects of prolonged sitting</a>.</p><p>When I've spent arguably too long at my desk, I have one of the <a href="https://www.tomsguide.com/best-picks/best-yoga-mats">best yoga mats</a> rolled out and on standby; when I get a spare few minutes, I'll work through a short mobility routine or gentle stretching, just to get things moving. It offers gentle muscle tension relief and allows me to move my joints and free up some space in my body.</p><p>It only takes 10 minutes, and I share the routine below, plus some benefits you can expect with regular practice. And remember, how well you <em>move </em>determines how well you <em>live</em> in the future. </p><h2 id="watch-10-minute-anti-sitting-routine-for-muscle-tension">Watch: 10-minute anti-sitting routine for muscle tension</h2><p>You can microdose these routines into your week; they're an anti-aging tool for healthier joints and more active muscles.</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><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/De7HT2jz6LF/" target="_blank">A post shared by Tom's Guide Fitness | Workout Tips &amp; Gear (@tomsguidefitness)</a></p><p>A photo posted by </p></blockquote></div><h2 id="what-are-the-benefits">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:1770px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="tuFVZg5LrEC557ZYWpFqPT" name="GettyImages-2234454694 legs over 40" alt="Blonde woman in pink workout gear against a blue sky backdrop holding her knee to her chest for a stretch" src="https://cdn.mos.cms.futurecdn.net/tuFVZg5LrEC557ZYWpFqPT-1920-80.jpg" mos="" align="middle" fullscreen="" width="1770" height="996" 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>Not only is a daily 10-minute yoga flow easy to build into a habit, but it also delivers both physiological and psychological benefits. Physically, it's perfect for moving your muscles and joints through range of motion, which can ease stiffness, release tension and open stiff joints. This is ideal to counter the slouching you probably do without noticing as you sit behind your phone or laptop.</p><p>Connecting with your breath allows you to breathe more deeply and rhythmically, activating the diaphragm and down-regulating your nervous system, which allows your body to enter rest-and-repair mode.</p><p>Short practices also improve sustainable consistency. By removing the barrier to exercise (equipment, time), you can improve mobility, strengthen your body and increase mental clarity after you step off the mat.</p><div><blockquote><p>Dynamic movement and stretching also stimulate blood flow and circulation, delivering oxygen and nutrients around your body. </p></blockquote></div><p>In just 10 minutes, this routine moves your spine through gentle extension and flexion, opening your chest and shoulders, releasing back tension and neck tightness that could impact posture. </p><p>Dynamic movement and stretching also stimulate blood flow and circulation, delivering oxygen and nutrients around your body. </p><p>You don't see results unless you stay consistent, so daily short-form stretching can help keep muscles and fascia more pliable and joints lubricated, meaning better mobility, flexibility and range of motion.</p><p>And finally, by regulating your nervous system, your heart rate and cortisol levels can lower, helping your body relax. If you tend to work from home often, a brief 10-minute sequence buffer between work and your personal life, which should help you find better balance.</p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="vGnNDN" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><p>Joints, ligaments and fascia respond well to low-impact movement, so a routine like this can serve you well if you're just starting. And remember, you might not notice progress straight away, but over time, you'll see huge benefits. Give it 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> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/workouts/no-not-pilates-when-my-lower-back-aches-from-sitting-all-day-this-is-the-10-minute-floor-routine-i-use-for-relief</link>
                                                                            <description>
                            <![CDATA[ If you sit for long periods, this short routine offers relief from muscle tension. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">hbVMJErCFyK79fcsCHb5TW</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/uk3XjrGhcjWsUkMgXiMLTF-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 26 Oct 2026 05:00:00 +0000</pubDate>                                                                                                                                <updated>Mon, 26 Oct 2026 10:09:32 +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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/uk3XjrGhcjWsUkMgXiMLTF-1920-80.jpg">
                                                            <media:credit><![CDATA[Future/ Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Sam at home performing upward dog stretch during workout]]></media:description>                                                            <media:text><![CDATA[Sam at home performing upward dog stretch during workout]]></media:text>
                                <media:title type="plain"><![CDATA[Sam at home performing upward dog stretch during workout]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/uk3XjrGhcjWsUkMgXiMLTF-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Despite my part-time job as a personal trainer, my full-time work as a fitness editor means I spend quite a lot of time sitting during the day. Sure, I like to get up and move around often, work out, and my dog gets plenty of long walks, but that doesn't always <a href="https://www.tomsguide.com/wellness/workouts/a-top-pilates-instructor-says-these-anti-desk-exercises-are-the-best-thing-you-can-do-to-counter-the-effects-of-sitting-at-any-age">counteract the effects of prolonged sitting</a>.</p><p>When I've spent arguably too long at my desk, I have one of the <a href="https://www.tomsguide.com/best-picks/best-yoga-mats">best yoga mats</a> rolled out and on standby; when I get a spare few minutes, I'll work through a short mobility routine or gentle stretching, just to get things moving. It offers gentle muscle tension relief and allows me to move my joints and free up some space in my body.</p><p>It only takes 10 minutes, and I share the routine below, plus some benefits you can expect with regular practice. And remember, how well you <em>move </em>determines how well you <em>live</em> in the future. </p><h2 id="watch-10-minute-anti-sitting-routine-for-muscle-tension">Watch: 10-minute anti-sitting routine for muscle tension</h2><p>You can microdose these routines into your week; they're an anti-aging tool for healthier joints and more active muscles.</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><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/De7HT2jz6LF/" target="_blank">A post shared by Tom's Guide Fitness | Workout Tips &amp; Gear (@tomsguidefitness)</a></p><p>A photo posted by </p></blockquote></div><h2 id="what-are-the-benefits">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:1770px;"><p class="vanilla-image-block" style="padding-top:56.27%;"><img id="tuFVZg5LrEC557ZYWpFqPT" name="GettyImages-2234454694 legs over 40" alt="Blonde woman in pink workout gear against a blue sky backdrop holding her knee to her chest for a stretch" src="https://cdn.mos.cms.futurecdn.net/tuFVZg5LrEC557ZYWpFqPT-1920-80.jpg" mos="" align="middle" fullscreen="" width="1770" height="996" 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>Not only is a daily 10-minute yoga flow easy to build into a habit, but it also delivers both physiological and psychological benefits. Physically, it's perfect for moving your muscles and joints through range of motion, which can ease stiffness, release tension and open stiff joints. This is ideal to counter the slouching you probably do without noticing as you sit behind your phone or laptop.</p><p>Connecting with your breath allows you to breathe more deeply and rhythmically, activating the diaphragm and down-regulating your nervous system, which allows your body to enter rest-and-repair mode.</p><p>Short practices also improve sustainable consistency. By removing the barrier to exercise (equipment, time), you can improve mobility, strengthen your body and increase mental clarity after you step off the mat.</p><div><blockquote><p>Dynamic movement and stretching also stimulate blood flow and circulation, delivering oxygen and nutrients around your body. </p></blockquote></div><p>In just 10 minutes, this routine moves your spine through gentle extension and flexion, opening your chest and shoulders, releasing back tension and neck tightness that could impact posture. </p><p>Dynamic movement and stretching also stimulate blood flow and circulation, delivering oxygen and nutrients around your body. </p><p>You don't see results unless you stay consistent, so daily short-form stretching can help keep muscles and fascia more pliable and joints lubricated, meaning better mobility, flexibility and range of motion.</p><p>And finally, by regulating your nervous system, your heart rate and cortisol levels can lower, helping your body relax. If you tend to work from home often, a brief 10-minute sequence buffer between work and your personal life, which should help you find better balance.</p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="vGnNDN" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><p>Joints, ligaments and fascia respond well to low-impact movement, so a routine like this can serve you well if you're just starting. And remember, you might not notice progress straight away, but over time, you'll see huge benefits. Give it 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[ A new study says this type of exercise is linked to a 36% lower risk of death, and I'm pretty surprised ]]></title>
                                                                                                <dc:content><![CDATA[ <p>If you needed any more reason to take up Pilates or yoga this year, emerging research just gave you one. According to a study, Pilates can lower the risk of death by 36%, with yoga not far behind. </p><p>We love a<a href="https://www.tomsguide.com/news/yoga-vs-pilates-which-burns-more-calories"> Pilates and yoga</a> practice here at Tom's Guide, but I was surprised by this news. Check out the details of the study below, and let us know whether this could convince you to start a practice by leaving a comment!</p><h2 id="what-is-the-study">What is the study?</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:3541px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="95rG4syEXKAauo2a8gHMsA" name="shutterstock_2175526501" alt="a woman doing Pilates" src="https://cdn.mos.cms.futurecdn.net/95rG4syEXKAauo2a8gHMsA-1920-80.jpg" mos="" align="middle" fullscreen="" width="3541" height="1992" attribution="" endorsement="" class="" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>A new <a href="https://news.asu.edu/20260904-health-and-medicine-asu-researchers-find-yoga-and-pilates-associated-longer-lifespans" target="_blank" rel="nofollow">study from Arizona State University</a> examined more than 55,000 U.S. adults and found that <strong>Pilates was associated with a 36% lower risk of death, while yoga was linked to a 27% lower risk.</strong> </p><p>Of 21 alternative health practices studied, Pilates and yoga were the only two associated with significantly lower mortality.</p><p>From the research, we can't establish a direct cause-and-effect relationship, but the findings raise interesting questions about the impact of movement, strength, balance, stress reduction and social connection on longevity and healthy aging.</p><div><blockquote><p>A new study from Arizona State University examined more than 55,000 U.S. adults and found that Pilates was associated with a 36% lower risk of death, while yoga was linked to a 27% lower risk. </p></blockquote></div><p>In a recent study, ASU Associate Professor Connor Sheehan and other researchers discovered that only yoga and Pilates "were associated with a significant decrease in the risk of death." </p><p>According to Sheehan, both practices improve balance and stress management and "offer a social component," which are "key contributors to longevity." However, despite the findings, further research is needed to determine causation.</p><p>We're living in a time where everyone wants to know the hacks for anti-aging and longevity. “Americans are spending billions on complementary and alternative medicine,” said Sheehan. “More than 40% of adults use at least one practice, from acupuncture to chiropractic care to specialized diets. But we actually know very little about whether any of these practices are associated with living longer.”</p><p>The researchers used "nationally representative data" from over 55,000 U.S. adults and linked to mortality records over roughly a decade. Many other practices like acupuncture and homeopathy showed "no significant association with mortality after researchers accounted for demographic and health differences between users and non-users."</p><p>Interestingly, the practices moving the needle most for boosting longevity are ones that combine movement, strengthening, social connection and mental wellbeing. That means it’s never too late to <a href="https://www.tomsguide.com/wellness/fitness/i-did-yoga-every-day-for-a-month-for-the-first-time-in-10-years-heres-what-happened-to-my-body">start a yoga routine</a>, take up <a href="https://www.tomsguide.com/features/3-things-i-wish-i-had-known-as-a-pilates-beginner">Pilates</a>, or even head to your local gym or community center to see what social exercise clubs you can join. </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/DewgqlzAdTN/" target="_blank">A post shared by Tom's Guide Fitness | Workout Tips &amp; Gear (@tomsguidefitness)</a></p><p>A photo posted by </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/fitness/forget-running-and-swimming-study-finds-this-sport-adds-10-years-to-your-life" target="_blank">Forget running and swimming — study finds this sport adds 10 years to your life</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/44-year-study-reveals-this-workout-reduces-dementia-risk-by-88-percent" target="_blank">New study reveals cycling can reduce dementia risk by 88%</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/new-study-shows-you-can-exercise-less-and-see-better-results-heres-exactly-how" target="_blank">Work out less and get better results — a new study says this is exactly how</a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness/a-new-study-says-this-type-of-exercise-is-linked-to-a-36-percent-lower-risk-of-death-and-im-pretty-surprised</link>
                                                                            <description>
                            <![CDATA[ A new study from Arizona State University examining more than 55,000 U.S. adults found thatPilates was associated with a 36% lower risk of death, while yoga was linked to a 27% lower risk. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">DwJQwkfPzpF64nVuLQMnRN</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/nZXwP72cy9fNqTqZKbMyZV-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 25 Oct 2026 08:45:00 +0000</pubDate>                                                                                                                                                                                                                                <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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/nZXwP72cy9fNqTqZKbMyZV-1920-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a woman holding a Pilates ball]]></media:description>                                                            <media:text><![CDATA[a woman holding a Pilates ball]]></media:text>
                                <media:title type="plain"><![CDATA[a woman holding a Pilates ball]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/nZXwP72cy9fNqTqZKbMyZV-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>If you needed any more reason to take up Pilates or yoga this year, emerging research just gave you one. According to a study, Pilates can lower the risk of death by 36%, with yoga not far behind. </p><p>We love a<a href="https://www.tomsguide.com/news/yoga-vs-pilates-which-burns-more-calories"> Pilates and yoga</a> practice here at Tom's Guide, but I was surprised by this news. Check out the details of the study below, and let us know whether this could convince you to start a practice by leaving a comment!</p><h2 id="what-is-the-study">What is the study?</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:3541px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="95rG4syEXKAauo2a8gHMsA" name="shutterstock_2175526501" alt="a woman doing Pilates" src="https://cdn.mos.cms.futurecdn.net/95rG4syEXKAauo2a8gHMsA-1920-80.jpg" mos="" align="middle" fullscreen="" width="3541" height="1992" attribution="" endorsement="" class="" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Shutterstock)</span></figcaption></figure><p>A new <a href="https://news.asu.edu/20260904-health-and-medicine-asu-researchers-find-yoga-and-pilates-associated-longer-lifespans" target="_blank" rel="nofollow">study from Arizona State University</a> examined more than 55,000 U.S. adults and found that <strong>Pilates was associated with a 36% lower risk of death, while yoga was linked to a 27% lower risk.</strong> </p><p>Of 21 alternative health practices studied, Pilates and yoga were the only two associated with significantly lower mortality.</p><p>From the research, we can't establish a direct cause-and-effect relationship, but the findings raise interesting questions about the impact of movement, strength, balance, stress reduction and social connection on longevity and healthy aging.</p><div><blockquote><p>A new study from Arizona State University examined more than 55,000 U.S. adults and found that Pilates was associated with a 36% lower risk of death, while yoga was linked to a 27% lower risk. </p></blockquote></div><p>In a recent study, ASU Associate Professor Connor Sheehan and other researchers discovered that only yoga and Pilates "were associated with a significant decrease in the risk of death." </p><p>According to Sheehan, both practices improve balance and stress management and "offer a social component," which are "key contributors to longevity." However, despite the findings, further research is needed to determine causation.</p><p>We're living in a time where everyone wants to know the hacks for anti-aging and longevity. “Americans are spending billions on complementary and alternative medicine,” said Sheehan. “More than 40% of adults use at least one practice, from acupuncture to chiropractic care to specialized diets. But we actually know very little about whether any of these practices are associated with living longer.”</p><p>The researchers used "nationally representative data" from over 55,000 U.S. adults and linked to mortality records over roughly a decade. Many other practices like acupuncture and homeopathy showed "no significant association with mortality after researchers accounted for demographic and health differences between users and non-users."</p><p>Interestingly, the practices moving the needle most for boosting longevity are ones that combine movement, strengthening, social connection and mental wellbeing. That means it’s never too late to <a href="https://www.tomsguide.com/wellness/fitness/i-did-yoga-every-day-for-a-month-for-the-first-time-in-10-years-heres-what-happened-to-my-body">start a yoga routine</a>, take up <a href="https://www.tomsguide.com/features/3-things-i-wish-i-had-known-as-a-pilates-beginner">Pilates</a>, or even head to your local gym or community center to see what social exercise clubs you can join. </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/DewgqlzAdTN/" target="_blank">A post shared by Tom's Guide Fitness | Workout Tips &amp; Gear (@tomsguidefitness)</a></p><p>A photo posted by </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/fitness/forget-running-and-swimming-study-finds-this-sport-adds-10-years-to-your-life" target="_blank">Forget running and swimming — study finds this sport adds 10 years to your life</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/44-year-study-reveals-this-workout-reduces-dementia-risk-by-88-percent" target="_blank">New study reveals cycling can reduce dementia risk by 88%</a></li><li><a href="https://www.tomsguide.com/wellness/fitness/new-study-shows-you-can-exercise-less-and-see-better-results-heres-exactly-how" target="_blank">Work out less and get better results — a new study says this is exactly how</a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I test running shoes and three great sneakers have been reduced to under $100 in the early Black Friday sales ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Just like everything else, running shoes have been getting more and more expensive in recent years, and that means the only way to get a quality shoe for less than $100 is generally to shop during sales.</p><p>Fortunately for those in need of new sneakers, the biggest sales period of the year is just kicking off, and I’ve been hunting for early Black Friday deals on excellent running shoes I’ve tested and rate highly.</p><p>I didn’t just want good deals; I wanted great ones that brought the price of top-quality shoes under $100, and I’ve managed to find three that fit the bill. </p><p>For me, the standout deal is the <a href="https://www.nike.com/t/zoom-fly-6-womens-road-racing-shoes-HZkwmBM5/FN8455-107" target="_blank" rel="nofollow">Nike Zoom Fly 6 reduced to $99 in the Nike sale</a>, but really, all three discounts are worth looking at if you need new running shoes.</p><h2 class="article-body__section" id="section-quick-links"><span>Quick links</span></h2><ul><li><strong>Nike Zoom Fly 6: </strong><a href="https://www.nike.com/t/zoom-fly-6-womens-road-racing-shoes-HZkwmBM5/FN8455-107" target="_blank" rel="nofollow"><strong>was $180 now $99 @ Nike</strong></a></li><li><strong>Puma Velocity Nitro 4: </strong><a href="https://www.amazon.com/PUMA-Velocity-Nitro-Running-Sneaker/dp/B0DWZGK2MS" target="_blank" rel="nofollow"><strong>was $140 now $99 @ Amazon</strong></a></li><li><strong>Brooks Glycerin 22: </strong><a href="https://www.amazon.com/Brooks-Mens-Glycerin-Neutral-Running/dp/B0D2Z2VMHT" target="_blank" rel="nofollow"><strong>was $165 now $99 @ Amazon</strong></a></li></ul><h3 class="article-body__section" id="section-running-shoe-deals"><span>Running shoe deals</span></h3><div class="product"><a data-dimension112="75b035fa-ce1a-11f1-b478-7995b52db904" data-action="Deal Block" data-label="Zoom Fly 6" data-dimension48="Zoom Fly 6" data-dimension25="$99" href="https://www.nike.com/t/zoom-fly-6-womens-road-racing-shoes-HZkwmBM5/FN8455-107" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1070px;"><p class="vanilla-image-block" style="padding-top:125.05%;"><img id="D329JcvPkxDYFUkphkT4NF" name="Nike Zoom Fly 6" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/D329JcvPkxDYFUkphkT4NF-1920-80.png" mos="" align="middle" fullscreen="" width="1070" height="1338" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Nike Zoom Fly 6 is one of the most underrated shoes on the market, in my opinion, because it's incredibly versatile. It's a plated trainer I enjoyed every kind of run in, from easy plods to mile reps on the track. One color of the women's shoe is just $99 right now, with varying discounts available on other colors.<a class="view-deal button" href="https://www.nike.com/t/zoom-fly-6-womens-road-racing-shoes-HZkwmBM5/FN8455-107" target="_blank" rel="nofollow" data-dimension112="75b035fa-ce1a-11f1-b478-7995b52db904" data-action="Deal Block" data-label="Zoom Fly 6" data-dimension48="Zoom Fly 6" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="d33ddeca-ce1a-11f1-bfe1-0773190acace" data-action="Deal Block" data-label="Velocity Nitro 4" data-dimension48="Velocity Nitro 4" data-dimension25="$99" href="https://www.amazon.com/PUMA-Velocity-Nitro-Running-Sneaker/dp/B0DWZGK2MS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="ZywwzQJdVP9nHZLB8cfyjh" name="Puma Velocity Nitro 4 sq" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZywwzQJdVP9nHZLB8cfyjh-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Velocity Nitro 4 is a very good value at its full price of $140, so the fact that multiple colors of the shoe are under $100 on Amazon right now is certainly enticing. I love the Velocity Nitro as a simple, comfortable daily trainer with a great outsole for runs in wet weather. I recently tested the Velocity Nitro 5 and didn't find it a notable upgrade, so I'd jump on this deal on the  Velocity Nitro 4 instead.<a class="view-deal button" href="https://www.amazon.com/PUMA-Velocity-Nitro-Running-Sneaker/dp/B0DWZGK2MS" target="_blank" rel="nofollow" data-dimension112="d33ddeca-ce1a-11f1-bfe1-0773190acace" data-action="Deal Block" data-label="Velocity Nitro 4" data-dimension48="Velocity Nitro 4" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="2bea1098-ce1b-11f1-ae16-db5e806068ff" data-action="Deal Block" data-label="Glycerin 22" data-dimension48="Glycerin 22" data-dimension25="$99" href="https://www.amazon.com/Brooks-Mens-Glycerin-Neutral-Running/dp/B0D2Z2VMHT" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:991px;"><p class="vanilla-image-block" style="padding-top:58.02%;"><img id="6aNiZBS2vURoK2YnfymeE9" name="Brooks Glycerin 22" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/6aNiZBS2vURoK2YnfymeE9-1920-80.png" mos="" align="middle" fullscreen="" width="991" height="575" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Glycerin 22 is an ultra comfortable, durable, cushioned running shoe ideal for beginners looking for a first sneaker or experienced runners who need a daily trainer for racking up big mileage. A few colors and sizes are under $100 on Amazon right now, a $66 saving off the full price.<a class="view-deal button" href="https://www.amazon.com/Brooks-Mens-Glycerin-Neutral-Running/dp/B0D2Z2VMHT" target="_blank" rel="nofollow" data-dimension112="2bea1098-ce1b-11f1-ae16-db5e806068ff" data-action="Deal Block" data-label="Glycerin 22" data-dimension48="Glycerin 22" data-dimension25="$99">View Deal</a></p></div><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/wellness/fitness/ive-been-in-a-serious-relationship-with-my-vagus-nerve-stimulator-for-30-days-to-see-if-it-would-decrease-my-stress-heres-why-im-breaking-up-with-it-already"><strong>I've been in a serious relationship with my vagus nerve stimulator for 30 days to see if it would decrease my stress — here's why I'm breaking up with it already</strong></a></li><li><a href="https://www.tomsguide.com/wellness/running/nike-pegasus-plus-2-review"><strong>I ran 40 miles in the Nike Pegasus Plus 2 and it’s worth the upgrade on the Pegasus 42</strong></a></li><li><a href="https://www.tomsguide.com/wellness/workouts/ive-been-coaching-my-72-year-old-dad-like-hes-30-heres-the-one-exercise-that-moves-the-needle-most-for-upper-body-strength-and-mobility"><strong>I coach my 72-year-old dad like he's 30: here's the one exercise that moves the needle most for upper-body strength and mobility</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/running/i-test-running-shoes-and-three-great-sneakers-have-been-reduced-to-under-usd100-in-the-early-black-friday-sales</link>
                                                                            <description>
                            <![CDATA[ Getting a great running shoe for under $100 isn’t easy these days, but the early Black Friday sales have already produced big discounts on three excellent sneakers I’ve tested. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">zdzUSaBKcCG6VWCKLCHiUf</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/Uc3xAddXsEw4UP4CNhCUe3-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 25 Oct 2026 06:30:00 +0000</pubDate>                                                                                                                                <updated>Sun, 25 Oct 2026 12:27:40 +0000</updated>
                                                                                                                                            <category><![CDATA[Running]]></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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/Uc3xAddXsEw4UP4CNhCUe3-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Nike Zoom Fly 6 ]]></media:description>                                                            <media:text><![CDATA[Nike Zoom Fly 6 ]]></media:text>
                                <media:title type="plain"><![CDATA[Nike Zoom Fly 6 ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/Uc3xAddXsEw4UP4CNhCUe3-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Just like everything else, running shoes have been getting more and more expensive in recent years, and that means the only way to get a quality shoe for less than $100 is generally to shop during sales.</p><p>Fortunately for those in need of new sneakers, the biggest sales period of the year is just kicking off, and I’ve been hunting for early Black Friday deals on excellent running shoes I’ve tested and rate highly.</p><p>I didn’t just want good deals; I wanted great ones that brought the price of top-quality shoes under $100, and I’ve managed to find three that fit the bill. </p><p>For me, the standout deal is the <a href="https://www.nike.com/t/zoom-fly-6-womens-road-racing-shoes-HZkwmBM5/FN8455-107" target="_blank" rel="nofollow">Nike Zoom Fly 6 reduced to $99 in the Nike sale</a>, but really, all three discounts are worth looking at if you need new running shoes.</p><h2 class="article-body__section" id="section-quick-links"><span>Quick links</span></h2><ul><li><strong>Nike Zoom Fly 6: </strong><a href="https://www.nike.com/t/zoom-fly-6-womens-road-racing-shoes-HZkwmBM5/FN8455-107" target="_blank" rel="nofollow"><strong>was $180 now $99 @ Nike</strong></a></li><li><strong>Puma Velocity Nitro 4: </strong><a href="https://www.amazon.com/PUMA-Velocity-Nitro-Running-Sneaker/dp/B0DWZGK2MS" target="_blank" rel="nofollow"><strong>was $140 now $99 @ Amazon</strong></a></li><li><strong>Brooks Glycerin 22: </strong><a href="https://www.amazon.com/Brooks-Mens-Glycerin-Neutral-Running/dp/B0D2Z2VMHT" target="_blank" rel="nofollow"><strong>was $165 now $99 @ Amazon</strong></a></li></ul><h3 class="article-body__section" id="section-running-shoe-deals"><span>Running shoe deals</span></h3><div class="product"><a data-dimension112="75b035fa-ce1a-11f1-b478-7995b52db904" data-action="Deal Block" data-label="Zoom Fly 6" data-dimension48="Zoom Fly 6" data-dimension25="$99" href="https://www.nike.com/t/zoom-fly-6-womens-road-racing-shoes-HZkwmBM5/FN8455-107" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1070px;"><p class="vanilla-image-block" style="padding-top:125.05%;"><img id="D329JcvPkxDYFUkphkT4NF" name="Nike Zoom Fly 6" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/D329JcvPkxDYFUkphkT4NF-1920-80.png" mos="" align="middle" fullscreen="" width="1070" height="1338" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Nike Zoom Fly 6 is one of the most underrated shoes on the market, in my opinion, because it's incredibly versatile. It's a plated trainer I enjoyed every kind of run in, from easy plods to mile reps on the track. One color of the women's shoe is just $99 right now, with varying discounts available on other colors.<a class="view-deal button" href="https://www.nike.com/t/zoom-fly-6-womens-road-racing-shoes-HZkwmBM5/FN8455-107" target="_blank" rel="nofollow" data-dimension112="75b035fa-ce1a-11f1-b478-7995b52db904" data-action="Deal Block" data-label="Zoom Fly 6" data-dimension48="Zoom Fly 6" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="d33ddeca-ce1a-11f1-bfe1-0773190acace" data-action="Deal Block" data-label="Velocity Nitro 4" data-dimension48="Velocity Nitro 4" data-dimension25="$99" href="https://www.amazon.com/PUMA-Velocity-Nitro-Running-Sneaker/dp/B0DWZGK2MS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="ZywwzQJdVP9nHZLB8cfyjh" name="Puma Velocity Nitro 4 sq" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZywwzQJdVP9nHZLB8cfyjh-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Velocity Nitro 4 is a very good value at its full price of $140, so the fact that multiple colors of the shoe are under $100 on Amazon right now is certainly enticing. I love the Velocity Nitro as a simple, comfortable daily trainer with a great outsole for runs in wet weather. I recently tested the Velocity Nitro 5 and didn't find it a notable upgrade, so I'd jump on this deal on the  Velocity Nitro 4 instead.<a class="view-deal button" href="https://www.amazon.com/PUMA-Velocity-Nitro-Running-Sneaker/dp/B0DWZGK2MS" target="_blank" rel="nofollow" data-dimension112="d33ddeca-ce1a-11f1-bfe1-0773190acace" data-action="Deal Block" data-label="Velocity Nitro 4" data-dimension48="Velocity Nitro 4" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="2bea1098-ce1b-11f1-ae16-db5e806068ff" data-action="Deal Block" data-label="Glycerin 22" data-dimension48="Glycerin 22" data-dimension25="$99" href="https://www.amazon.com/Brooks-Mens-Glycerin-Neutral-Running/dp/B0D2Z2VMHT" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:991px;"><p class="vanilla-image-block" style="padding-top:58.02%;"><img id="6aNiZBS2vURoK2YnfymeE9" name="Brooks Glycerin 22" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/6aNiZBS2vURoK2YnfymeE9-1920-80.png" mos="" align="middle" fullscreen="" width="991" height="575" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Glycerin 22 is an ultra comfortable, durable, cushioned running shoe ideal for beginners looking for a first sneaker or experienced runners who need a daily trainer for racking up big mileage. A few colors and sizes are under $100 on Amazon right now, a $66 saving off the full price.<a class="view-deal button" href="https://www.amazon.com/Brooks-Mens-Glycerin-Neutral-Running/dp/B0D2Z2VMHT" target="_blank" rel="nofollow" data-dimension112="2bea1098-ce1b-11f1-ae16-db5e806068ff" data-action="Deal Block" data-label="Glycerin 22" data-dimension48="Glycerin 22" data-dimension25="$99">View Deal</a></p></div><h3 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h3><ul><li><a href="https://www.tomsguide.com/wellness/fitness/ive-been-in-a-serious-relationship-with-my-vagus-nerve-stimulator-for-30-days-to-see-if-it-would-decrease-my-stress-heres-why-im-breaking-up-with-it-already"><strong>I've been in a serious relationship with my vagus nerve stimulator for 30 days to see if it would decrease my stress — here's why I'm breaking up with it already</strong></a></li><li><a href="https://www.tomsguide.com/wellness/running/nike-pegasus-plus-2-review"><strong>I ran 40 miles in the Nike Pegasus Plus 2 and it’s worth the upgrade on the Pegasus 42</strong></a></li><li><a href="https://www.tomsguide.com/wellness/workouts/ive-been-coaching-my-72-year-old-dad-like-hes-30-heres-the-one-exercise-that-moves-the-needle-most-for-upper-body-strength-and-mobility"><strong>I coach my 72-year-old dad like he's 30: here's the one exercise that moves the needle most for upper-body strength and mobility</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Over 60? These are the 4 most important beginning-level exercises to master ]]></title>
                                                                                                <dc:content><![CDATA[ <p>It’s never too late to start exercising. As a certified personal trainer, I work with so many clients in their 60s, 70s, and even 80s that are embarking on their very first fitness journeys. And when they start seeing real progress, it’s thrilling for both of us.</p><p>It’s important to always start with the basics, though, so when I meet with a beginning-level senior client for the first time, I start them off with the following four exercises. These moves are relatively friendly on the joints, help build the strength needed for more advanced exercises, and can make everyday activities easier and safer. </p><p>You won’t need any equipment right off the bat, but as you get stronger, you can start using a set of <a href="https://www.tomsguide.com/wellness/fitness/best-adjustable-dumbbells"><u>dumbbells</u></a> for a few of these exercises. </p><h2 id="how-to-do-the-four-exercises-2">How to do the four exercises</h2><p>Consult a doctor before trying any new activity. They may caution against certain movements based on your health history.</p><p>This workout is appropriate for most beginners, but getting your form right is crucial. Consider meeting with a certified personal trainer who can teach you how to do the moves correctly. Exercising with improper form can cause pain or injury. </p><p>You’ll just need a section of bare wall and a sturdy chair for this workout. </p><p>Start with one set of 10 reps for chair squats, standing dead bug, and wall push-ups, and hold the wall plank for 30 seconds. If that feels easy, add an additional set or two, gradually increase your reps to 12-15, and hold the wall plank for 45-60 seconds. Eventually, you’ll want to complete 3 sets for each exercise, 3-4 times per week. Once that stops being a challenge, you’ll be ready for a more advanced routine. </p><p>Here’s how to do the exercises:</p><h3 class="article-body__section" id="section-1-chair-squats"><span>1. Chair squats</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Bo5CcPvgMmoDY8PLN4wDHU" name="chair squat" alt="sit to stand squat" src="https://cdn.mos.cms.futurecdn.net/Bo5CcPvgMmoDY8PLN4wDHU-1920-80.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><ul><li>Stand tall in front of a chair with your feet hip-width apart.</li><li>Engage your core muscles, drawing your belly button towards your spine.</li><li>Hinge your hips behind you.</li><li>Bend your knees and slowly lower your hips towards the seat.</li><li>Lengthen your arms in front of you for balance.</li><li>Tap your hips onto the seat, then stand back up.</li><li>Continue for 10-15 reps.</li></ul><h3 class="article-body__section" id="section-2-wall-planks"><span>2. Wall planks</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/K4ZijUE-o1A" allowfullscreen=""></iframe></div></div><ul><li>Stand facing a wall.</li><li>Place your forearms on the wall. Keep your elbows aligned with your shoulders.</li><li>Engage your core muscles.</li><li>Step your feet away from the wall.</li><li>Maintain a straight line with your body, from the top of your head to your toes.</li><li>Hold for 30-60 seconds.</li></ul><h3 class="article-body__section" id="section-3-standing-deadbug"><span>3. Standing deadbug</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/DERetW6rStg" allowfullscreen=""></iframe></div></div><ul><li>Stand with your feet hip-width apart and your back against the wall.</li><li>Engage your core muscles.</li><li>Lift your left arm above your head while bringing your right knee to a 90-degree angle.</li><li>Pause briefly.</li><li>Lower your left arm and right leg.</li><li>Lift your right arm above your head while bringing your left knee to a 90-degree angle.</li><li>Pause briefly.</li><li>Lower your right arm and left leg.</li><li>Continue alternating between your two sides for 10-15 reps each side.</li></ul><h3 class="article-body__section" id="section-4-wall-push-ups"><span>4. Wall push-ups</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="EsTwpfEEGnBW9zVKV8L4L5" name="wall push up" alt="a man doing push ups on a wall" src="https://cdn.mos.cms.futurecdn.net/EsTwpfEEGnBW9zVKV8L4L5-1920-80.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><ul><li>Stand facing a wall.</li><li>Lengthen your arms and place your hands against the wall.</li><li>Engage your core muscles.</li><li>Bend your elbows and lower your chest towards the wall, keeping your head, hips, and feet in alignment.</li><li>Push yourself back up to the starting position.</li><li>Continue for 10-15 reps</li></ul><h2 id="benefits-of-these-exercises">Benefits of these exercises</h2><p>This workout targets major muscle groups in the lower body, upper body, and core, responsible for everyday movements like walking, getting up from a seated position, pushing yourself up, and balancing.</p><p>These exercises are beginner versions of more standard movements. Mastering chair squats prepares you for bodyweight squats, and mastering wall planks, standing deadbugs, and wall push-ups prepares you for regular push-ups, planks, and deadbugs. The chair and wall provide assistance as you strengthen your body progressively and with good form.</p><p>Since this workout is done standing, it’s appropriate for seniors who have trouble getting onto the floor. For those unable to do standard push ups, planks, and deadbugs, there are easy ways to make the standing versions of these moves more challenging: small weights can be held during the standing deadbug, and stepping further away from the wall will amp up the difficulty of the wall plank and wall push up. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.js" async=""></script><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-to-be-more-mobile-in-their-60s-and-70s-3-low-impact-exercises-you-should-start-with" target="_blank"><strong>I teach people to be more mobile in their 60s and 70s: 3 low-impact exercises you should start with</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness/forget-burpees-the-pilates-burpee-is-beginner-friendly-and-low-impact-and-youll-love-it" target="_blank"><strong>Forget burpees —the 'Pilates burpee' is beginner-friendly and low-impact (and you’ll love it)</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/a-yoga-instructor-says-this-is-the-5-minute-yoga-routine-you-need-for-strong-and-mobile-hips-and-core-muscles" target="_blank"><strong>A yoga instructor says this is the 5-minute yoga routine you need for strong and mobile hips and core muscles</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/workouts/over-60-these-are-the-4-most-important-beginning-level-exercises-to-master</link>
                                                                            <description>
                            <![CDATA[ Here are the four beginner exercises everyone should be doing over 60 ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">kSnrdq7eG6AKKNJWkZKXaC</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/VH7pGYGYnwv4MHqjEzLGVE-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 25 Oct 2026 04:30:00 +0000</pubDate>                                                                                                                                <updated>Sun, 25 Oct 2026 12:28: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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/VH7pGYGYnwv4MHqjEzLGVE-1920-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a middle-aged women in workout clothes ]]></media:description>                                                            <media:text><![CDATA[a middle-aged women in workout clothes ]]></media:text>
                                <media:title type="plain"><![CDATA[a middle-aged women in workout clothes ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/VH7pGYGYnwv4MHqjEzLGVE-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>It’s never too late to start exercising. As a certified personal trainer, I work with so many clients in their 60s, 70s, and even 80s that are embarking on their very first fitness journeys. And when they start seeing real progress, it’s thrilling for both of us.</p><p>It’s important to always start with the basics, though, so when I meet with a beginning-level senior client for the first time, I start them off with the following four exercises. These moves are relatively friendly on the joints, help build the strength needed for more advanced exercises, and can make everyday activities easier and safer. </p><p>You won’t need any equipment right off the bat, but as you get stronger, you can start using a set of <a href="https://www.tomsguide.com/wellness/fitness/best-adjustable-dumbbells"><u>dumbbells</u></a> for a few of these exercises. </p><h2 id="how-to-do-the-four-exercises-2">How to do the four exercises</h2><p>Consult a doctor before trying any new activity. They may caution against certain movements based on your health history.</p><p>This workout is appropriate for most beginners, but getting your form right is crucial. Consider meeting with a certified personal trainer who can teach you how to do the moves correctly. Exercising with improper form can cause pain or injury. </p><p>You’ll just need a section of bare wall and a sturdy chair for this workout. </p><p>Start with one set of 10 reps for chair squats, standing dead bug, and wall push-ups, and hold the wall plank for 30 seconds. If that feels easy, add an additional set or two, gradually increase your reps to 12-15, and hold the wall plank for 45-60 seconds. Eventually, you’ll want to complete 3 sets for each exercise, 3-4 times per week. Once that stops being a challenge, you’ll be ready for a more advanced routine. </p><p>Here’s how to do the exercises:</p><h3 class="article-body__section" id="section-1-chair-squats"><span>1. Chair squats</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Bo5CcPvgMmoDY8PLN4wDHU" name="chair squat" alt="sit to stand squat" src="https://cdn.mos.cms.futurecdn.net/Bo5CcPvgMmoDY8PLN4wDHU-1920-80.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><ul><li>Stand tall in front of a chair with your feet hip-width apart.</li><li>Engage your core muscles, drawing your belly button towards your spine.</li><li>Hinge your hips behind you.</li><li>Bend your knees and slowly lower your hips towards the seat.</li><li>Lengthen your arms in front of you for balance.</li><li>Tap your hips onto the seat, then stand back up.</li><li>Continue for 10-15 reps.</li></ul><h3 class="article-body__section" id="section-2-wall-planks"><span>2. Wall planks</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/K4ZijUE-o1A" allowfullscreen=""></iframe></div></div><ul><li>Stand facing a wall.</li><li>Place your forearms on the wall. Keep your elbows aligned with your shoulders.</li><li>Engage your core muscles.</li><li>Step your feet away from the wall.</li><li>Maintain a straight line with your body, from the top of your head to your toes.</li><li>Hold for 30-60 seconds.</li></ul><h3 class="article-body__section" id="section-3-standing-deadbug"><span>3. Standing deadbug</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/DERetW6rStg" allowfullscreen=""></iframe></div></div><ul><li>Stand with your feet hip-width apart and your back against the wall.</li><li>Engage your core muscles.</li><li>Lift your left arm above your head while bringing your right knee to a 90-degree angle.</li><li>Pause briefly.</li><li>Lower your left arm and right leg.</li><li>Lift your right arm above your head while bringing your left knee to a 90-degree angle.</li><li>Pause briefly.</li><li>Lower your right arm and left leg.</li><li>Continue alternating between your two sides for 10-15 reps each side.</li></ul><h3 class="article-body__section" id="section-4-wall-push-ups"><span>4. Wall push-ups</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="EsTwpfEEGnBW9zVKV8L4L5" name="wall push up" alt="a man doing push ups on a wall" src="https://cdn.mos.cms.futurecdn.net/EsTwpfEEGnBW9zVKV8L4L5-1920-80.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><ul><li>Stand facing a wall.</li><li>Lengthen your arms and place your hands against the wall.</li><li>Engage your core muscles.</li><li>Bend your elbows and lower your chest towards the wall, keeping your head, hips, and feet in alignment.</li><li>Push yourself back up to the starting position.</li><li>Continue for 10-15 reps</li></ul><h2 id="benefits-of-these-exercises">Benefits of these exercises</h2><p>This workout targets major muscle groups in the lower body, upper body, and core, responsible for everyday movements like walking, getting up from a seated position, pushing yourself up, and balancing.</p><p>These exercises are beginner versions of more standard movements. Mastering chair squats prepares you for bodyweight squats, and mastering wall planks, standing deadbugs, and wall push-ups prepares you for regular push-ups, planks, and deadbugs. The chair and wall provide assistance as you strengthen your body progressively and with good form.</p><p>Since this workout is done standing, it’s appropriate for seniors who have trouble getting onto the floor. For those unable to do standard push ups, planks, and deadbugs, there are easy ways to make the standing versions of these moves more challenging: small weights can be held during the standing deadbug, and stepping further away from the wall will amp up the difficulty of the wall plank and wall push up. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.js" async=""></script><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-to-be-more-mobile-in-their-60s-and-70s-3-low-impact-exercises-you-should-start-with" target="_blank"><strong>I teach people to be more mobile in their 60s and 70s: 3 low-impact exercises you should start with</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness/forget-burpees-the-pilates-burpee-is-beginner-friendly-and-low-impact-and-youll-love-it" target="_blank"><strong>Forget burpees —the 'Pilates burpee' is beginner-friendly and low-impact (and you’ll love it)</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/a-yoga-instructor-says-this-is-the-5-minute-yoga-routine-you-need-for-strong-and-mobile-hips-and-core-muscles" target="_blank"><strong>A yoga instructor says this is the 5-minute yoga routine you need for strong and mobile hips and core muscles</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I review running shoes for a living: Here’s the pair I’ve chosen to wear for my 7th marathon, and it’s probably not what you’re expecting ]]></title>
                                                                                                <dc:content><![CDATA[ <p>As a fitness editor, I spend my days writing about running shoes, so choosing a pair to wear on race day often feels (almost) as difficult as the race itself. The good news is, I’m currently a few days away from my seventh marathon, and I’ve settled on my race-day shoe — and it’s probably not what you’re expecting. </p><p>After testing most of the <a href="https://www.tomsguide.com/best-picks/best-carbon-fiber-running-shoes">best carbon-plate running shoes</a> on the market, I’ve chosen the <a href="https://www.tomsguide.com/wellness/running/weve-run-60-miles-in-the-new-balance-supercomp-rebel-v1-and-its-our-new-favorite-fast-training-shoe">New Balance Supercomp Rebel v1 </a>as my race-day shoe, even though New Balance markets it as an everyday runner rather than a racer. Read on to find out why this shoe in particular made it into my hand luggage as I fly to Frankfurt, Germany, for my next 26.2-mile race. </p><div class="product"><a data-dimension112="bd876ce0-cd6b-11f1-852c-df34de4e5afd" data-action="Deal Block" data-label="SuperComp Rebel v1" data-dimension48="SuperComp Rebel v1" data-dimension25="$199" href="https://www.newbalance.com/pd/supercomp-rebel/MREBXV1_RU-FTW-814193-PMG-NA.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:782px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="6RQwMy7NdQfbpW3fu4bSyM" name="nb sc rebel" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/6RQwMy7NdQfbpW3fu4bSyM-1920-80.jpg" mos="" align="middle" fullscreen="" width="782" height="782" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.newbalance.com/pd/supercomp-rebel/MREBXV1_RU-FTW-814193-PMG-NA.html" target="_blank" rel="nofollow" data-dimension112="bd876ce0-cd6b-11f1-852c-df34de4e5afd" data-action="Deal Block" data-label="SuperComp Rebel v1" data-dimension48="SuperComp Rebel v1" data-dimension25="$199">SuperComp Rebel v1: $199</a></strong><br />The New Balance SC Rebel v1 is a super trainer, designed for fast, everyday miles, with a good amount of versatility. <a class="view-deal button" href="https://www.newbalance.com/pd/supercomp-rebel/MREBXV1_RU-FTW-814193-PMG-NA.html" target="_blank" rel="nofollow" data-dimension112="bd876ce0-cd6b-11f1-852c-df34de4e5afd" data-action="Deal Block" data-label="SuperComp Rebel v1" data-dimension48="SuperComp Rebel v1" data-dimension25="$199">View Deal</a></p></div><h3 class="article-body__section" id="section-the-carbon-infused-plate-is-more-flexible-than-other-racing-shoes"><span>The carbon-infused plate is more flexible than other racing shoes </span></h3><p>Ok, I ever-so-slightly lied — this shoe isn’t completely plateless. New Balance markets this shoe as a fast shoe for everyday runs, or a supertrainer, if you will. A lot of runners use the New Balance Rebel v1 for training and the New Balance SuperComp Elite v6 for race day, yet despite running a PR in the New Balance SC Elite v5, every time I run in the Elite v6, I get a hotspot on the bottom of my heel, where the carbon plate sits, often leaving me with a blister.</p><p>The Rebel v1 has a carbon-infused Pebax plate, which is a little more flexible than the plate used in the SuperComp Elite v6, making it more comfortable for regular use. In other words, the plate is plastic, not carbon. But don’t let this put you off — it makes the shoe more affordable than a lot of carbon racers, and it’s actually more comfortable underfoot. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Kn8XS32weRzoWD4sWZY7YN" name="New Balance SC Rebel v1" alt="New Balance SC Rebel v1" src="https://cdn.mos.cms.futurecdn.net/Kn8XS32weRzoWD4sWZY7YN-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><h3 class="article-body__section" id="section-2-it-s-energetic-and-bouncy"><span>2. It’s energetic and bouncy </span></h3><p>After running over 100 miles in this shoe, I think it still has enough speed underfoot to be a contender for race day, while also feeling fantastic on slower, easy miles. It’s not the most stable or supportive if you’re running slowly, but it comes into its own on longer runs at race pace and tempo sessions. </p><p>I’ve worn this shoe for a 22-mile long run, with a few miles at race pace, and found it coped with everything I threw at it. I personally find it a lot more stable than a lot of the more aggressive carbon plates, and it’s definitely an exciting shoe to run in. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="RgY8yAxbryySNcPqUnSsJN" name="New Balance SC Rebel v1" alt="New Balance SC Rebel v1" src="https://cdn.mos.cms.futurecdn.net/RgY8yAxbryySNcPqUnSsJN-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><h3 class="article-body__section" id="section-3-it-has-great-traction-on-wet-roads"><span>3. It has great traction on wet roads </span></h3><p>My running coach used to tell me, "Control what you can control," and one thing no runner can control on the day of the race is the weather. Frankfurt looks pretty wet on race day, which is another reason I’m choosing the SuperComp Rebel v1, which, in my testing, has a good amount of grip even on wet roads.</p><p>Overall, I’ve been impressed with the versatility of this trainer, making it one of my favorite running shoes I’ve tested this year. Whether it propels me to a PR remains to be seen, but if you’re looking for a good all-rounder with a great deal of traction and a fun ride underfoot, this is a shoe to consider.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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><strong></strong><a href="https://www.tomsguide.com/wellness/running/rheon-running-shorts-are-being-used-by-top-road-track-and-trail-runners-i-spoke-to-an-expert-to-find-out-more-about-the-tech"><strong>Rheon running shorts are being used by top road, track and trail runners — I spoke to an expert to find out more about the tech</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/running/i-tested-shoes-from-5-up-and-coming-running-brands-here-are-the-ones-worth-your-money"><strong>I tested shoes from 5 up-and-coming running brands — here are the ones worth your money</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/no-squats-i-just-tried-this-8-minute-chair-workout-and-its-perfect-for-seniors-beginners-and-anyone-looking-to-build-strength-without-impact" target="_blank"><strong>No squats! I just tried this 8-minute chair workout, and it’s perfect for seniors, beginners, and anyone looking to build strength without impact</strong></a><strong></strong></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/running/i-review-running-shoes-for-a-living-heres-the-pair-ive-chosen-to-wear-for-my-7th-marathon-and-its-probably-not-what-youre-expecting</link>
                                                                            <description>
                            <![CDATA[ I spend my days reviewing running shoes, and this is the pair I've picked for my next marathon. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">YqGFqc3y5dN9nKedtAvDjb</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/DBq8nVh6ng4RYNy9kU4GEZ-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 24 Oct 2026 10:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Running]]></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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/DBq8nVh6ng4RYNy9kU4GEZ-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[New Balance SC Rebel v1 and Jane McGuire ]]></media:description>                                                            <media:text><![CDATA[New Balance SC Rebel v1 and Jane McGuire ]]></media:text>
                                <media:title type="plain"><![CDATA[New Balance SC Rebel v1 and Jane McGuire ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/DBq8nVh6ng4RYNy9kU4GEZ-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>As a fitness editor, I spend my days writing about running shoes, so choosing a pair to wear on race day often feels (almost) as difficult as the race itself. The good news is, I’m currently a few days away from my seventh marathon, and I’ve settled on my race-day shoe — and it’s probably not what you’re expecting. </p><p>After testing most of the <a href="https://www.tomsguide.com/best-picks/best-carbon-fiber-running-shoes">best carbon-plate running shoes</a> on the market, I’ve chosen the <a href="https://www.tomsguide.com/wellness/running/weve-run-60-miles-in-the-new-balance-supercomp-rebel-v1-and-its-our-new-favorite-fast-training-shoe">New Balance Supercomp Rebel v1 </a>as my race-day shoe, even though New Balance markets it as an everyday runner rather than a racer. Read on to find out why this shoe in particular made it into my hand luggage as I fly to Frankfurt, Germany, for my next 26.2-mile race. </p><div class="product"><a data-dimension112="bd876ce0-cd6b-11f1-852c-df34de4e5afd" data-action="Deal Block" data-label="SuperComp Rebel v1" data-dimension48="SuperComp Rebel v1" data-dimension25="$199" href="https://www.newbalance.com/pd/supercomp-rebel/MREBXV1_RU-FTW-814193-PMG-NA.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:782px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="6RQwMy7NdQfbpW3fu4bSyM" name="nb sc rebel" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/6RQwMy7NdQfbpW3fu4bSyM-1920-80.jpg" mos="" align="middle" fullscreen="" width="782" height="782" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.newbalance.com/pd/supercomp-rebel/MREBXV1_RU-FTW-814193-PMG-NA.html" target="_blank" rel="nofollow" data-dimension112="bd876ce0-cd6b-11f1-852c-df34de4e5afd" data-action="Deal Block" data-label="SuperComp Rebel v1" data-dimension48="SuperComp Rebel v1" data-dimension25="$199">SuperComp Rebel v1: $199</a></strong><br />The New Balance SC Rebel v1 is a super trainer, designed for fast, everyday miles, with a good amount of versatility. <a class="view-deal button" href="https://www.newbalance.com/pd/supercomp-rebel/MREBXV1_RU-FTW-814193-PMG-NA.html" target="_blank" rel="nofollow" data-dimension112="bd876ce0-cd6b-11f1-852c-df34de4e5afd" data-action="Deal Block" data-label="SuperComp Rebel v1" data-dimension48="SuperComp Rebel v1" data-dimension25="$199">View Deal</a></p></div><h3 class="article-body__section" id="section-the-carbon-infused-plate-is-more-flexible-than-other-racing-shoes"><span>The carbon-infused plate is more flexible than other racing shoes </span></h3><p>Ok, I ever-so-slightly lied — this shoe isn’t completely plateless. New Balance markets this shoe as a fast shoe for everyday runs, or a supertrainer, if you will. A lot of runners use the New Balance Rebel v1 for training and the New Balance SuperComp Elite v6 for race day, yet despite running a PR in the New Balance SC Elite v5, every time I run in the Elite v6, I get a hotspot on the bottom of my heel, where the carbon plate sits, often leaving me with a blister.</p><p>The Rebel v1 has a carbon-infused Pebax plate, which is a little more flexible than the plate used in the SuperComp Elite v6, making it more comfortable for regular use. In other words, the plate is plastic, not carbon. But don’t let this put you off — it makes the shoe more affordable than a lot of carbon racers, and it’s actually more comfortable underfoot. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Kn8XS32weRzoWD4sWZY7YN" name="New Balance SC Rebel v1" alt="New Balance SC Rebel v1" src="https://cdn.mos.cms.futurecdn.net/Kn8XS32weRzoWD4sWZY7YN-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><h3 class="article-body__section" id="section-2-it-s-energetic-and-bouncy"><span>2. It’s energetic and bouncy </span></h3><p>After running over 100 miles in this shoe, I think it still has enough speed underfoot to be a contender for race day, while also feeling fantastic on slower, easy miles. It’s not the most stable or supportive if you’re running slowly, but it comes into its own on longer runs at race pace and tempo sessions. </p><p>I’ve worn this shoe for a 22-mile long run, with a few miles at race pace, and found it coped with everything I threw at it. I personally find it a lot more stable than a lot of the more aggressive carbon plates, and it’s definitely an exciting shoe to run in. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="RgY8yAxbryySNcPqUnSsJN" name="New Balance SC Rebel v1" alt="New Balance SC Rebel v1" src="https://cdn.mos.cms.futurecdn.net/RgY8yAxbryySNcPqUnSsJN-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><h3 class="article-body__section" id="section-3-it-has-great-traction-on-wet-roads"><span>3. It has great traction on wet roads </span></h3><p>My running coach used to tell me, "Control what you can control," and one thing no runner can control on the day of the race is the weather. Frankfurt looks pretty wet on race day, which is another reason I’m choosing the SuperComp Rebel v1, which, in my testing, has a good amount of grip even on wet roads.</p><p>Overall, I’ve been impressed with the versatility of this trainer, making it one of my favorite running shoes I’ve tested this year. Whether it propels me to a PR remains to be seen, but if you’re looking for a good all-rounder with a great deal of traction and a fun ride underfoot, this is a shoe to consider.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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><strong></strong><a href="https://www.tomsguide.com/wellness/running/rheon-running-shorts-are-being-used-by-top-road-track-and-trail-runners-i-spoke-to-an-expert-to-find-out-more-about-the-tech"><strong>Rheon running shorts are being used by top road, track and trail runners — I spoke to an expert to find out more about the tech</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/running/i-tested-shoes-from-5-up-and-coming-running-brands-here-are-the-ones-worth-your-money"><strong>I tested shoes from 5 up-and-coming running brands — here are the ones worth your money</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/no-squats-i-just-tried-this-8-minute-chair-workout-and-its-perfect-for-seniors-beginners-and-anyone-looking-to-build-strength-without-impact" target="_blank"><strong>No squats! I just tried this 8-minute chair workout, and it’s perfect for seniors, beginners, and anyone looking to build strength without impact</strong></a><strong></strong></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I asked a longevity expert for 3 daily bodyweight exercises that maintain muscle mass in your 40s — here's what they chose ]]></title>
                                                                                                <dc:content><![CDATA[ <p>"Longevity" is the word on everyone's lips lately, and we all seem dialed into the best ways to boost longevity as birthdays relentlessly come and go. Recently, I spoke with expert Leslie Kenny, co-founder of the prestigious<a href="https://oxfordlongevityproject.org/" target="_blank" rel="nofollow"> Oxford Longevity Project</a>, who shared three exercises she recommends for maintaining muscle as you age.</p><p>"One of the most important things we can do for healthy aging is preserve our muscle mass," Kenny says. "From our 30s onwards, we can gradually lose muscle, particularly if we’re sedentary. This becomes increasingly important in our 40s, when hormonal changes, particularly during perimenopause for women, can make maintaining muscle more challenging."</p><p>The good news is that you don’t need an expensive gym membership or complicated equipment to start protecting your muscles. Three simple bodyweight exercises can make a real difference. We share them below. </p><h2 id="what-are-the-three-bodyweight-exercises-for-longevity">What are the three bodyweight exercises for longevity?</h2><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-1-squats-for-strong-legs-metabolic-health-and-maintaining-independence"><span>1. Squats: For strong legs, metabolic health and maintaining independence</span></h3><div><blockquote><p>When we keep our largest muscle groups strong and active, we’re doing much more than protecting our mobility. We’re also supporting the body’s ability to regulate inflammation, which is particularly important as we age.</p></blockquote></div><iframe src="https://content.jwplatform.com/players/YFgWfQv7.html" id="YFgWfQv7" title="Project Move - Goblet Dumbbell Squat" width="960" height="540" frameborder="0" scrolling="auto" allowfullscreen=""></iframe><p>"My colleague at the Oxford Longevity Project, Sir Muir Gray, always says that the quickest route to a care home is when you can no longer sit down on the toilet and get up again unaided," says Kenny.</p><p>"It sounds rather blunt, but he makes an incredibly important point. The ability to sit down and stand up independently is one of the fundamental movements that allows us to remain independent as we age.</p><p>"<a href="https://www.tomsguide.com/how-to/squats-how-to-do-them-and-the-benefits-for-building-leg-strength-and-muscle">Squats </a>strengthen some of the biggest muscle groups in our bodies, particularly the quadriceps in our thighs and the gluteal muscles in our buttocks. But here’s something many people don’t realize: our muscles aren’t just there to move us around. They’re also endocrine organs, producing signaling molecules called <strong>myokines</strong>, some of which have powerful anti-inflammatory effects."</p><p>Contracting muscles during exercise means releasing myokines into the bloodstream that can help regulate inflammation, support metabolic health and communicate with other organs, including the brain.</p><p><strong>Tips:</strong></p><ul><li>Start with 10–15 slow, controlled squats, keeping your feet approximately shoulder-width apart and your knees tracking in the same direction as your toes.</li><li>If you’re a beginner, simply practice sitting down on a chair and standing up again without using your hands. It’s a surprisingly effective exercise.</li><li>As you get stronger, slow the lowering phase to three or four seconds, or progress to more challenging variations. And remember, the goal isn’t just to be able to do squats in your 40s. It’s to still be able to get up from the toilet unaided in your 90s!</li></ul><h3 class="article-body__section" id="section-2-push-ups-for-upper-body-strength-and-bone-health"><span>2. Push-ups: For upper-body strength and bone health</span></h3><div><blockquote><p>Push-ups are also a weight-bearing exercise, placing mechanical stress through the arms and shoulders.</p></blockquote></div><iframe src="https://content.jwplatform.com/players/neMFB64d.html" id="neMFB64d" title="Tg Fitness - Push-up" width="960" height="540" frameborder="0" scrolling="auto" allowfullscreen=""></iframe><p>"<a href="https://www.tomsguide.com/how-to/how-to-do-a-push-up">Push-ups</a> are wonderful because they work several muscle groups simultaneously, including the chest, shoulders, triceps and core," Kenny tells us. "Upper-body strength is particularly important for women, who generally have less upper-body muscle mass than men.</p><p>"Push-ups are also a weight-bearing exercise, placing mechanical stress through the arms and shoulders, which can help support bone health alongside a comprehensive resistance-training program. They also help us preserve the strength needed for everyday activities, from lifting shopping bags to pushing ourselves up from the floor."</p><p><strong>Tips:</strong></p><ul><li>If a traditional floor push-up feels too difficult, start with your hands against a wall or sturdy kitchen counter.</li><li>Keep your body in a straight line, engage your abdominal muscles and lower yourself slowly.</li><li>Aim for 8–12 controlled repetitions, choosing a variation that makes the final few repetitions challenging without compromising your technique.</li><li>As you become stronger, gradually lower the incline until you can perform push-ups on the floor.</li></ul><h3 class="article-body__section" id="section-3-reverse-lunges-for-balance-stability-and-preserving-muscle-as-we-age"><span>3. Reverse lunges: For balance, stability and preserving muscle as we age</span></h3><div><blockquote><p>Reverse lunges strengthen the quadriceps, glutes and hamstrings while also challenging balance and coordination.</p></blockquote></div><iframe src="https://content.jwplatform.com/players/OEawmTNt.html" id="OEawmTNt" title="TG Fitness- Reverse Lunges" width="960" height="540" frameborder="0" scrolling="auto" allowfullscreen=""></iframe><p>"<a href="https://www.tomsguide.com/news/i-did-100-lunges-a-day-for-a-week-heres-what-happened">Reverse lunges</a> strengthen the quadriceps, glutes and hamstrings while also challenging balance and coordination," Kenny says. "I particularly like single-leg exercises because they help address differences in strength between our left and right sides. </p><p>"They also challenge the stabilizing muscles around the hips, knees and ankles, which are essential for walking, climbing stairs and reducing the risk of falls as we age. And because lunges recruit several large muscle groups, they provide another opportunity to stimulate muscle contractions and the release of beneficial myokines."</p><p><strong>Tips:</strong></p><ul><li>Stand tall, step one foot backward and lower yourself slowly, bending both knees as far as is comfortable.</li><li>Push through your front foot to return to standing.</li><li>Start with 8–10 repetitions on each leg. If balance is difficult, hold onto a sturdy chair or kitchen counter.</li><li>For an extra challenge, pause briefly at the bottom of each repetition or slow down the movement.</li></ul><h3 class="article-body__section" id="section-final-tips-from-a-longevity-expert"><span>Final tips from a longevity expert</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="RRWjFooeZLxh24DZtMhcQ9" name="shutterstock_1397209415 color walk" alt="Woman outdoors in nature walking with a backpack on smiling" src="https://cdn.mos.cms.futurecdn.net/RRWjFooeZLxh24DZtMhcQ9-1920-80.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: Shutterstock)</span></figcaption></figure><p>"Muscle isn’t just about strength or looking toned. It’s metabolically active tissue that helps regulate blood glucose, supports insulin sensitivity, protects our joints and bones, and helps us remain independent as we get older," explains Kenny. </p><p>"The real secret to maintaining muscle mass isn’t doing hundreds of repetitions every day. It’s<a href="https://www.tomsguide.com/features/progressive-overload-what-is-it-and-how-does-it-help-build-muscle-and-strength"> <strong>progressive overload</strong> </a>— gradually increasing the challenge to your muscles, so they have a reason to stay strong. You can do this by increasing repetitions, slowing movements, progressing to more demanding variations, or eventually adding resistance."</p><div><blockquote><p>"I often remind people that muscle is our longevity currency. The strength we build and preserve in our 40s is an investment in how well we move, function and live in our 70s, 80s and beyond. After all, we don’t just want to live longer. We want to remain strong enough to enjoy those extra years!"</p></blockquote></div><p>Kenny says these three exercises "make an excellent short daily movement routine, but for meaningful muscle maintenance, I recommend performing <strong>challenging resistance-training sessions at least two or three times a week</strong>, allowing muscles sufficient time to recover. Ideally, a complete strength program should also include pulling movements to strengthen the back."</p><p>Finally, consider your<a href="https://www.tomsguide.com/wellness/fitness/how-much-protein-do-you-need-to-build-muscle"> protein intake</a>. While exercise stimulates muscle growth and maintenance, protein provides amino acids which are essential for repairing and rebuilding muscle tissue. <br /><br />"I often remind people that <strong>muscle is our longevity currency</strong>. The strength we build and preserve in our 40s is an investment in how well we move, function and live in our 70s, 80s and beyond. After all, we don’t just want to live longer. We want to remain strong enough to enjoy those extra years!"</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OKB5GW"></div>                            </div>                            <script src="https://kwizly.com/embed/OKB5GW.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/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> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/workouts/i-asked-a-longevity-expert-for-3-daily-bodyweight-exercises-that-maintain-muscle-mass-in-your-40s-heres-what-they-chose</link>
                                                                            <description>
                            <![CDATA[ Leslie Kenny, who is a longevity expert and co-founder of the prestigious Oxford Longevity Project, shares three exercises to maintain muscle mass after 30. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">iYsvEMxTHtgqqvjpCuXKx5</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/57CkKyN2EnRxj33ha7k9Kf-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 24 Oct 2026 04:15:00 +0000</pubDate>                                                                                                                                <updated>Sat, 24 Oct 2026 12:21:24 +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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/57CkKyN2EnRxj33ha7k9Kf-1920-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Woman in her 40s or 50s in red workout gear outdoors performing a squat on grass]]></media:description>                                                            <media:text><![CDATA[Woman in her 40s or 50s in red workout gear outdoors performing a squat on grass]]></media:text>
                                <media:title type="plain"><![CDATA[Woman in her 40s or 50s in red workout gear outdoors performing a squat on grass]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/57CkKyN2EnRxj33ha7k9Kf-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>"Longevity" is the word on everyone's lips lately, and we all seem dialed into the best ways to boost longevity as birthdays relentlessly come and go. Recently, I spoke with expert Leslie Kenny, co-founder of the prestigious<a href="https://oxfordlongevityproject.org/" target="_blank" rel="nofollow"> Oxford Longevity Project</a>, who shared three exercises she recommends for maintaining muscle as you age.</p><p>"One of the most important things we can do for healthy aging is preserve our muscle mass," Kenny says. "From our 30s onwards, we can gradually lose muscle, particularly if we’re sedentary. This becomes increasingly important in our 40s, when hormonal changes, particularly during perimenopause for women, can make maintaining muscle more challenging."</p><p>The good news is that you don’t need an expensive gym membership or complicated equipment to start protecting your muscles. Three simple bodyweight exercises can make a real difference. We share them below. </p><h2 id="what-are-the-three-bodyweight-exercises-for-longevity">What are the three bodyweight exercises for longevity?</h2><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-1-squats-for-strong-legs-metabolic-health-and-maintaining-independence"><span>1. Squats: For strong legs, metabolic health and maintaining independence</span></h3><div><blockquote><p>When we keep our largest muscle groups strong and active, we’re doing much more than protecting our mobility. We’re also supporting the body’s ability to regulate inflammation, which is particularly important as we age.</p></blockquote></div><iframe src="https://content.jwplatform.com/players/YFgWfQv7.html" id="YFgWfQv7" title="Project Move - Goblet Dumbbell Squat" width="960" height="540" frameborder="0" scrolling="auto" allowfullscreen=""></iframe><p>"My colleague at the Oxford Longevity Project, Sir Muir Gray, always says that the quickest route to a care home is when you can no longer sit down on the toilet and get up again unaided," says Kenny.</p><p>"It sounds rather blunt, but he makes an incredibly important point. The ability to sit down and stand up independently is one of the fundamental movements that allows us to remain independent as we age.</p><p>"<a href="https://www.tomsguide.com/how-to/squats-how-to-do-them-and-the-benefits-for-building-leg-strength-and-muscle">Squats </a>strengthen some of the biggest muscle groups in our bodies, particularly the quadriceps in our thighs and the gluteal muscles in our buttocks. But here’s something many people don’t realize: our muscles aren’t just there to move us around. They’re also endocrine organs, producing signaling molecules called <strong>myokines</strong>, some of which have powerful anti-inflammatory effects."</p><p>Contracting muscles during exercise means releasing myokines into the bloodstream that can help regulate inflammation, support metabolic health and communicate with other organs, including the brain.</p><p><strong>Tips:</strong></p><ul><li>Start with 10–15 slow, controlled squats, keeping your feet approximately shoulder-width apart and your knees tracking in the same direction as your toes.</li><li>If you’re a beginner, simply practice sitting down on a chair and standing up again without using your hands. It’s a surprisingly effective exercise.</li><li>As you get stronger, slow the lowering phase to three or four seconds, or progress to more challenging variations. And remember, the goal isn’t just to be able to do squats in your 40s. It’s to still be able to get up from the toilet unaided in your 90s!</li></ul><h3 class="article-body__section" id="section-2-push-ups-for-upper-body-strength-and-bone-health"><span>2. Push-ups: For upper-body strength and bone health</span></h3><div><blockquote><p>Push-ups are also a weight-bearing exercise, placing mechanical stress through the arms and shoulders.</p></blockquote></div><iframe src="https://content.jwplatform.com/players/neMFB64d.html" id="neMFB64d" title="Tg Fitness - Push-up" width="960" height="540" frameborder="0" scrolling="auto" allowfullscreen=""></iframe><p>"<a href="https://www.tomsguide.com/how-to/how-to-do-a-push-up">Push-ups</a> are wonderful because they work several muscle groups simultaneously, including the chest, shoulders, triceps and core," Kenny tells us. "Upper-body strength is particularly important for women, who generally have less upper-body muscle mass than men.</p><p>"Push-ups are also a weight-bearing exercise, placing mechanical stress through the arms and shoulders, which can help support bone health alongside a comprehensive resistance-training program. They also help us preserve the strength needed for everyday activities, from lifting shopping bags to pushing ourselves up from the floor."</p><p><strong>Tips:</strong></p><ul><li>If a traditional floor push-up feels too difficult, start with your hands against a wall or sturdy kitchen counter.</li><li>Keep your body in a straight line, engage your abdominal muscles and lower yourself slowly.</li><li>Aim for 8–12 controlled repetitions, choosing a variation that makes the final few repetitions challenging without compromising your technique.</li><li>As you become stronger, gradually lower the incline until you can perform push-ups on the floor.</li></ul><h3 class="article-body__section" id="section-3-reverse-lunges-for-balance-stability-and-preserving-muscle-as-we-age"><span>3. Reverse lunges: For balance, stability and preserving muscle as we age</span></h3><div><blockquote><p>Reverse lunges strengthen the quadriceps, glutes and hamstrings while also challenging balance and coordination.</p></blockquote></div><iframe src="https://content.jwplatform.com/players/OEawmTNt.html" id="OEawmTNt" title="TG Fitness- Reverse Lunges" width="960" height="540" frameborder="0" scrolling="auto" allowfullscreen=""></iframe><p>"<a href="https://www.tomsguide.com/news/i-did-100-lunges-a-day-for-a-week-heres-what-happened">Reverse lunges</a> strengthen the quadriceps, glutes and hamstrings while also challenging balance and coordination," Kenny says. "I particularly like single-leg exercises because they help address differences in strength between our left and right sides. </p><p>"They also challenge the stabilizing muscles around the hips, knees and ankles, which are essential for walking, climbing stairs and reducing the risk of falls as we age. And because lunges recruit several large muscle groups, they provide another opportunity to stimulate muscle contractions and the release of beneficial myokines."</p><p><strong>Tips:</strong></p><ul><li>Stand tall, step one foot backward and lower yourself slowly, bending both knees as far as is comfortable.</li><li>Push through your front foot to return to standing.</li><li>Start with 8–10 repetitions on each leg. If balance is difficult, hold onto a sturdy chair or kitchen counter.</li><li>For an extra challenge, pause briefly at the bottom of each repetition or slow down the movement.</li></ul><h3 class="article-body__section" id="section-final-tips-from-a-longevity-expert"><span>Final tips from a longevity expert</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="RRWjFooeZLxh24DZtMhcQ9" name="shutterstock_1397209415 color walk" alt="Woman outdoors in nature walking with a backpack on smiling" src="https://cdn.mos.cms.futurecdn.net/RRWjFooeZLxh24DZtMhcQ9-1920-80.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: Shutterstock)</span></figcaption></figure><p>"Muscle isn’t just about strength or looking toned. It’s metabolically active tissue that helps regulate blood glucose, supports insulin sensitivity, protects our joints and bones, and helps us remain independent as we get older," explains Kenny. </p><p>"The real secret to maintaining muscle mass isn’t doing hundreds of repetitions every day. It’s<a href="https://www.tomsguide.com/features/progressive-overload-what-is-it-and-how-does-it-help-build-muscle-and-strength"> <strong>progressive overload</strong> </a>— gradually increasing the challenge to your muscles, so they have a reason to stay strong. You can do this by increasing repetitions, slowing movements, progressing to more demanding variations, or eventually adding resistance."</p><div><blockquote><p>"I often remind people that muscle is our longevity currency. The strength we build and preserve in our 40s is an investment in how well we move, function and live in our 70s, 80s and beyond. After all, we don’t just want to live longer. We want to remain strong enough to enjoy those extra years!"</p></blockquote></div><p>Kenny says these three exercises "make an excellent short daily movement routine, but for meaningful muscle maintenance, I recommend performing <strong>challenging resistance-training sessions at least two or three times a week</strong>, allowing muscles sufficient time to recover. Ideally, a complete strength program should also include pulling movements to strengthen the back."</p><p>Finally, consider your<a href="https://www.tomsguide.com/wellness/fitness/how-much-protein-do-you-need-to-build-muscle"> protein intake</a>. While exercise stimulates muscle growth and maintenance, protein provides amino acids which are essential for repairing and rebuilding muscle tissue. <br /><br />"I often remind people that <strong>muscle is our longevity currency</strong>. The strength we build and preserve in our 40s is an investment in how well we move, function and live in our 70s, 80s and beyond. After all, we don’t just want to live longer. We want to remain strong enough to enjoy those extra years!"</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-OKB5GW"></div>                            </div>                            <script src="https://kwizly.com/embed/OKB5GW.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/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[ Golf gift guide: 25 awesome products that any golfer is sure to love ]]></title>
                                                                                                <dc:content><![CDATA[ <p>I am obsessed with golf. I am also addicted to golf equipment and apparel. I also love shopping for friends and loved ones (and myself), so I figured, why not combine those passions and round up the best golf gifts for any time of year? </p><p>Over the years, <strong>I've tested hundreds of golf products</strong>. I've played with the best <a href="https://www.tomsguide.com/wellness/smartwatches/i-tested-the-3-best-golf-apps-for-apple-watch-heres-my-favorite">game-tracking tool, Arccos</a>, and I've tried some <a href="https://www.tomsguide.com/wellness/fitness/stop-wasting-money-on-a-new-driver-every-year-get-this-simple-training-aid-insteadhttps://www.tomsguide.com/wellness/fitness/ive-been-golfing-for-4-years-and-these-are-the-gadgets-that-helped-me-improve">cool training aids</a>. I've used <a href="https://www.tomsguide.com/wellness/fitness/sick-of-your-golf-bag-looking-boring-i-tried-two-you-can-customize">custom golf bags</a> and <a href="https://www.tomsguide.com/wellness/fitness/foresight-gc3-launch-monitor-6-month-impressions">high-end launch monitors</a>. </p><p>I've seen it all and tried most of it (and yet I'm still not very good at golf, which proves two things: golf is hard, and equipment doesn't automatically make you good). </p><p>I've created the<strong> ultimate list of gifts for the golf lover in your life, including options for every budget</strong>. I could have included way more products, but I kept it to a manageable list of things I actually use (or would happily receive as a gift) so you can be confident you're getting something they'll like.</p><p>I <strong>didn't include highly preference-based products</strong>, especially for experienced golfers. </p><p>For example, you won't find golf balls on the list, as serious golfers typically have one ball they play, and unless you know which one it is, balls are almost guaranteed to be returned. The same goes for clubs — many golfers get fitted for the right clubs, so buying them a random 5-wood won't do the job. </p><p>Instead, we're <strong>focused on useful items </strong>golfers might not have that<strong> aren't custom or tied to specific preferences.</strong></p><p>Does that mean you can't buy balls or clubs if you know what to get? Of course not. If you know your favorite golfer plays <a href="https://www.amazon.com/Titleist-Pro-V1-2025/dp/B0DPN7QZ9R" target="_blank" rel="nofollow">Titleist Pro V1</a> or <a href="https://www.amazon.com/VICE-Drip-Version-Balls-Black/dp/B08SR9ZLSY" target="_blank" rel="nofollow">Vice Pro</a> (my golf ball of choice), for example, then by all means grab them a dozen balls and call it a day! </p><h3 class="article-body__section" id="section-quick-links-my-top-5-gifts-for-golfers"><span>Quick Links: My top 5 gifts for golfers</span></h3><ol start="1"><li><strong></strong><a href="https://www.arccosgolf.com/pages/us-air-sl" target="_blank" rel="nofollow"><strong>Arccos Air game tracking system</strong></a><strong></strong></li><li><strong></strong><a href="https://pathpalgolf.com/pages/complete-training-package" target="_blank" rel="nofollow"><strong>PathPal training aid</strong></a><strong></strong></li><li><a href="https://www.quince.com/shop/activewear/shop-by-activity/mens-golf" target="_blank" rel="nofollow"><strong>Quince affordable golf apparel</strong></a></li><li><a href="https://hackmotion.com/hackmotion-sensor-4/" target="_blank" rel="nofollow"><strong>HackMotion Sensor 4</strong></a></li><li><strong></strong><a href="https://vesselgolf.com/products/player-v-pro-stand-eden" target="_blank" rel="nofollow"><strong>Vessel Golf Player V Pro stand bag</strong></a><strong></strong></li></ol><h3 class="article-body__section" id="section-golf-apparel"><span>Golf apparel</span></h3><div class="product"><a data-dimension112="5595db6c-cee7-11f1-be82-93287409d51a" data-action="Deal Block" data-label="Quince Golf apparel: starting at $29" data-dimension48="Quince Golf apparel: starting at $29" href="https://www.quince.com/shop/activewear/shop-by-activity/mens-golf" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:399px;"><p class="vanilla-image-block" style="padding-top:125.56%;"><img id="78FdcUTCg7ciEJsjfamBbH" name="Quincepants" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/78FdcUTCg7ciEJsjfamBbH-1920-80.png" mos="" align="middle" fullscreen="" width="399" height="501" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><a href="https://www.quince.com/shop/activewear/shop-by-activity/mens-golf?sortBy=PRICE_LOW_TO_HIGH" target="_blank" rel="nofollow" data-dimension112="5595db6c-cee7-11f1-be82-93287409d51a" data-action="Deal Block" data-label="Quince Golf apparel: starting at $29" data-dimension48="Quince Golf apparel: starting at $29" data-dimension25=""><strong>Quince Golf apparel: starting at $29</strong></a><br />Golf clothing is usually quite expensive. Most of my favorite pieces are $90 or more. But Quince is setting out to disrupt the trend by offering nice clothing at affordable prices. I tried <a href="https://www.quince.com/men/protech-golf-pants?color=riviera-blue" target="_blank" rel="nofollow">Quince golf pants</a>, a <a href="https://www.quince.com/men/recycled-flowknit-performance-polo?color=olive&amp;gender=men&amp;size=xl" target="_blank" rel="nofollow">comfy polo</a> and more and found them to be on the same level of comfort as stuff from more expensive brands. They're a great gift because you don't need to spend tons of money to get stylish, comfortable golf clothing for the player in your life.<a class="view-deal button" href="https://www.quince.com/shop/activewear/shop-by-activity/mens-golf" target="_blank" rel="nofollow" data-dimension112="5595db6c-cee7-11f1-be82-93287409d51a" data-action="Deal Block" data-label="Quince Golf apparel: starting at $29" data-dimension48="Quince Golf apparel: starting at $29" data-dimension25="">View Deal</a></p></div><div class="product"><a data-dimension112="5595dbda-cee7-11f1-a76f-915c31fabff3" data-action="Deal Block" data-label="3-Pack Golf Web Belt" data-dimension48="3-Pack Golf Web Belt" data-dimension25="$17" href="https://www.amazon.com/Nike-Mens-Pack-White-Gray/dp/B004NRNOG8" 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:108.25%;"><img id="brpVgfiASDYCT3oYqfMCiT" name="71H621JjWtL._AC_SX679_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/brpVgfiASDYCT3oYqfMCiT-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="735" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nike-Mens-Pack-White-Gray/dp/B004NRNOG8" target="_blank" rel="nofollow" data-dimension112="5595dbda-cee7-11f1-a76f-915c31fabff3" data-action="Deal Block" data-label="3-Pack Golf Web Belt" data-dimension48="3-Pack Golf Web Belt" data-dimension25="$17">3-Pack Golf Web Belt: was $24 now $17</a></strong><br />Good belts are a must for golf attire, and our favorite value option is these stretchy Nike belts. This three-pack makes a great gift for golfers, considering it's one of those things you can never have enough of. Having color options allows golfers to complete their outfits, as the belt is often the finishing touch to a style.<a class="view-deal button" href="https://www.amazon.com/Nike-Mens-Pack-White-Gray/dp/B004NRNOG8" target="_blank" rel="nofollow" data-dimension112="5595dbda-cee7-11f1-a76f-915c31fabff3" data-action="Deal Block" data-label="3-Pack Golf Web Belt" data-dimension48="3-Pack Golf Web Belt" data-dimension25="$17">View Deal</a></p></div><div class="product"><a data-dimension112="5595dc48-cee7-11f1-8e38-49873a24b8e8" data-action="Deal Block" data-label="Braided Belt" data-dimension48="Braided Belt" data-dimension25="$49" href="https://thebyrd.com/products/the-braided-byrd-golf-belt-black-capped-chickadee" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:476px;"><p class="vanilla-image-block" style="padding-top:141.18%;"><img id="suZWaqKcciv8MbdqmJrErQ" name="Braided Belt" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/suZWaqKcciv8MbdqmJrErQ-1920-80.png" mos="" align="middle" fullscreen="" width="476" height="672" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://thebyrd.com/products/the-braided-byrd-golf-belt-black-capped-chickadee" target="_blank" rel="nofollow" data-dimension112="5595dc48-cee7-11f1-8e38-49873a24b8e8" data-action="Deal Block" data-label="Braided Belt" data-dimension48="Braided Belt" data-dimension25="$49">Braided Belt: was $55 now $49</a></strong><br />On the course, golfers need to carry a divot tool, ball marker, tees, balls and anything else they need to make their round enjoyable. The Byrd Belt is a fun gift that turns many of those products into a belt. And it's a nice belt that I wear off the course just as much as on it.<a class="view-deal button" href="https://thebyrd.com/products/the-braided-byrd-golf-belt-black-capped-chickadee" target="_blank" rel="nofollow" data-dimension112="5595dc48-cee7-11f1-8e38-49873a24b8e8" data-action="Deal Block" data-label="Braided Belt" data-dimension48="Braided Belt" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="805b5326-d38e-11f1-a50c-cda0970364f8" data-action="Deal Block" data-label="Cotton Stretch Belt" data-dimension48="Cotton Stretch Belt" data-dimension25="$138" href="https://www.johnnie-o.com/products/jmbl1510-cotton-stretch-belt-azalea" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1200px;"><p class="vanilla-image-block" style="padding-top:125.00%;"><img id="uw74fjXmXFi5y3rDd7gA6P" name="Cotton Stretch Belt" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/uw74fjXmXFi5y3rDd7gA6P-1920-80.png" mos="" align="middle" fullscreen="" width="1200" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.johnnie-o.com/products/jmbl1510-cotton-stretch-belt-azalea" target="_blank" rel="nofollow" data-dimension112="805b5326-d38e-11f1-a50c-cda0970364f8" data-action="Deal Block" data-label="Cotton Stretch Belt" data-dimension48="Cotton Stretch Belt" data-dimension25="$138">Cotton Stretch Belt: $138</a></strong><br />Okay, so this belt is rather expensive, but I'm not kidding when I say it's the best belt I've ever owned. It fits perfectly, stretches well and comes in vibrant colors that complete any outfit. A pop of color could be exactly what the golfer in your life needs, and this belt delivers.<a class="view-deal button" href="https://www.johnnie-o.com/products/jmbl1510-cotton-stretch-belt-azalea" target="_blank" rel="nofollow" data-dimension112="805b5326-d38e-11f1-a50c-cda0970364f8" data-action="Deal Block" data-label="Cotton Stretch Belt" data-dimension48="Cotton Stretch Belt" data-dimension25="$138">View Deal</a></p></div><h3 class="article-body__section" id="section-golf-accessories"><span>Golf Accessories</span></h3><div class="product"><a data-dimension112="5595dd2e-cee7-11f1-aba9-ffa42f4dfc82" data-action="Deal Block" data-label="Odyssey Putt Target" data-dimension48="Odyssey Putt Target" data-dimension25="$8" href="https://www.pgatoursuperstore.com/odyssey-putt-target/1018975.html?cgid=golf-accessories-training-aids" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="2vAvha7DKVgfkaEV6A7ofg" name="Odyssey Putt Target" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/2vAvha7DKVgfkaEV6A7ofg-1920-80.png" mos="" align="middle" fullscreen="" width="500" height="500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.pgatoursuperstore.com/odyssey-putt-target/1018975.html?cgid=golf-accessories-training-aids" target="_blank" rel="nofollow" data-dimension112="5595dd2e-cee7-11f1-aba9-ffa42f4dfc82" data-action="Deal Block" data-label="Odyssey Putt Target" data-dimension48="Odyssey Putt Target" data-dimension25="$8">Odyssey Putt Target: $8</a></strong><br />This is the perfect gift for the golfer who seemingly has everything. It's a putting target the size of a golf hole, so when the putting green is busy and all the holes are taken, they can throw this down and get their warm-up putts in. It's thoughtful and cheap — two of my favorite elements of any gift.<a class="view-deal button" href="https://www.pgatoursuperstore.com/odyssey-putt-target/1018975.html?cgid=golf-accessories-training-aids" target="_blank" rel="nofollow" data-dimension112="5595dd2e-cee7-11f1-aba9-ffa42f4dfc82" data-action="Deal Block" data-label="Odyssey Putt Target" data-dimension48="Odyssey Putt Target" data-dimension25="$8">View Deal</a></p></div><div class="product"><a data-dimension112="fc108c40-d4cc-11f1-84ea-533589136996" data-action="Deal Block" data-label="Pro Splash Brush" data-dimension48="Pro Splash Brush" data-dimension25="$25" href="https://www.pgatoursuperstore.com/pro-caddy-splash-brush/1178594001.html" 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="YL55cSjYnsYxtBgMzY6jEN" name="Pro Splash Brush" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/YL55cSjYnsYxtBgMzY6jEN-1920-80.png" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.pgatoursuperstore.com/pro-caddy-splash-brush/1178594001.html" target="_blank" rel="nofollow" data-dimension112="fc108c40-d4cc-11f1-84ea-533589136996" data-action="Deal Block" data-label="Pro Splash Brush" data-dimension48="Pro Splash Brush" data-dimension25="$25">Pro Splash Brush: $25</a></strong><br />No one likes dirty golf clubs, and the Caddy Splash Pro is the best way I've found to keep them clean. I never play a round without one clipped to my bag (I used to roll with the <a href="https://www.pgatoursuperstore.com/original-caddy-splash-brush/2000000054572.html" target="_blank" rel="nofollow">original Caddy Splash</a>, but I've since upgraded to this one).<a class="view-deal button" href="https://www.pgatoursuperstore.com/pro-caddy-splash-brush/1178594001.html" target="_blank" rel="nofollow" data-dimension112="fc108c40-d4cc-11f1-84ea-533589136996" data-action="Deal Block" data-label="Pro Splash Brush" data-dimension48="Pro Splash Brush" data-dimension25="$25">View Deal</a></p></div><div class="product"><a data-dimension112="5595dd9c-cee7-11f1-a1d7-5350f755f5ef" data-action="Deal Block" data-label="Magnetic Towel" data-dimension48="Magnetic Towel" data-dimension25="$30" href="https://ghostgolf.com/collections/towels/products/magnetic-towel-greenside" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="NqKhij8fZ47hpCeqjJpSP4" name="golf towel.png" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/NqKhij8fZ47hpCeqjJpSP4-1920-80.png" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://ghostgolf.com/collections/towels/products/magnetic-towel-greenside" target="_blank" rel="nofollow" data-dimension112="5595dd9c-cee7-11f1-a1d7-5350f755f5ef" data-action="Deal Block" data-label="Magnetic Towel" data-dimension48="Magnetic Towel" data-dimension25="$30">Magnetic Towel: $30</a></strong><br />Another piece of equipment a golfer can never have enough of is a fresh golf towel for their bag. We like this magnetic one that can be picked up off the ground quickly with a club and has plenty of great color options. Ghost Golf has quickly risen to become one of the most popular brands, and it's largely thanks to making high-quality gear.<a class="view-deal button" href="https://ghostgolf.com/collections/towels/products/magnetic-towel-greenside" target="_blank" rel="nofollow" data-dimension112="5595dd9c-cee7-11f1-a1d7-5350f755f5ef" data-action="Deal Block" data-label="Magnetic Towel" data-dimension48="Magnetic Towel" data-dimension25="$30">View Deal</a></p></div><div class="product"><a data-dimension112="5595de0a-cee7-11f1-a203-cd3ca1ab7d84" data-action="Deal Block" data-label="2 Layer Golf Trunk Organizer" data-dimension48="2 Layer Golf Trunk Organizer" data-dimension25="$32" href="https://www.amazon.com/Organizer-Waterproof-Ventilated-Compartment-Accessories/dp/B09PZZ1QRM" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1408px;"><p class="vanilla-image-block" style="padding-top:106.53%;"><img id="6q42gErTa4JearPAxSRMtk" name="2 Layer Golf Trunk Organizer" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/6q42gErTa4JearPAxSRMtk-1920-80.png" mos="" align="middle" fullscreen="" width="1408" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Organizer-Waterproof-Ventilated-Compartment-Accessories/dp/B09PZZ1QRM" target="_blank" rel="nofollow" data-dimension112="5595de0a-cee7-11f1-a203-cd3ca1ab7d84" data-action="Deal Block" data-label="2 Layer Golf Trunk Organizer" data-dimension48="2 Layer Golf Trunk Organizer" data-dimension25="$32">2 Layer Golf Trunk Organizer: was $35 now $32</a></strong><br />I have this organizer in my trunk, and it's helped me make sure I always have a couple of pairs of golf shoes (I have a couple dozen pairs, so it's good to have some handy) and all my accessories ready to go. Sure, your golfer might just throw the stuff loose in their trunk, but why do that when this organizer is readily available?<a class="view-deal button" href="https://www.amazon.com/Organizer-Waterproof-Ventilated-Compartment-Accessories/dp/B09PZZ1QRM" target="_blank" rel="nofollow" data-dimension112="5595de0a-cee7-11f1-a203-cd3ca1ab7d84" data-action="Deal Block" data-label="2 Layer Golf Trunk Organizer" data-dimension48="2 Layer Golf Trunk Organizer" data-dimension25="$32">View Deal</a></p></div><div class="product"><a data-dimension112="5595de78-cee7-11f1-9b2d-cd38528f2fe5" data-action="Deal Block" data-label="Golf Tumbler 30oz" data-dimension48="Golf Tumbler 30oz" data-dimension25="$39" href="https://www.tallytumbler.com/products/golf-tally-tumbler" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="gB4epwH8ghPQ6HDFKXgF9n" name="Golf Tumbler" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gB4epwH8ghPQ6HDFKXgF9n-1920-80.png" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.tallytumbler.com/products/golf-tally-tumbler" target="_blank" rel="nofollow" data-dimension112="5595de78-cee7-11f1-9b2d-cd38528f2fe5" data-action="Deal Block" data-label="Golf Tumbler 30oz" data-dimension48="Golf Tumbler 30oz" data-dimension25="$39">Golf Tumbler 30oz: $39</a></strong><br />I just tried one of these tumblers, and it's a fun novelty to be sure! Importantly, it also works as a good cup for keeping your liquids cold (or warm) while offering a fun way to track your golf score and stats. If you think the golfer in your life has everything, this might be the perfect gift to get them that they haven't snagged yet. And if you prefer a smaller cup, you can get a <a href="https://www.tallytumbler.com/products/golf-tally-tumbler-20oz" target="_blank" rel="nofollow">20oz version</a>, too.<a class="view-deal button" href="https://www.tallytumbler.com/products/golf-tally-tumbler" target="_blank" rel="nofollow" data-dimension112="5595de78-cee7-11f1-9b2d-cd38528f2fe5" data-action="Deal Block" data-label="Golf Tumbler 30oz" data-dimension48="Golf Tumbler 30oz" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="fc108d08-d4cc-11f1-a997-d3bdd2d1a9e8" data-action="Deal Block" data-label="Advent Calendar" data-dimension48="Advent Calendar" data-dimension25="$89" href="https://www.vicegolf.com/products/vice-advent-calendar-12-days-of-vicemas-24-balls" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="H9GSGpxBDmrtAncCL58BVo" name="Advent Calendar" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/H9GSGpxBDmrtAncCL58BVo-1920-80.png" mos="" align="middle" fullscreen="" width="2500" height="2500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>This is the perfect gift for the golfer who already has everything. A bunch of fun, limited-edition golf balls in an advent calendar will keep them entertained all holiday season, and they'll end up with two dozen cool golf balls when all is said and done.<a class="view-deal button" href="https://www.vicegolf.com/products/vice-advent-calendar-12-days-of-vicemas-24-balls" target="_blank" rel="nofollow" data-dimension112="fc108d08-d4cc-11f1-a997-d3bdd2d1a9e8" data-action="Deal Block" data-label="Advent Calendar" data-dimension48="Advent Calendar" data-dimension25="$89">View Deal</a></p></div><div class="product"><a data-dimension112="5595dee6-cee7-11f1-b1d4-d39090d8916e" data-action="Deal Block" data-label="Golf Organizer" data-dimension48="Golf Organizer" data-dimension25="$59" href="https://www.amazon.com/Morvat-Organizer-Accessories-Organize-Equipment/dp/B0799QHWF6/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1447px;"><p class="vanilla-image-block" style="padding-top:103.66%;"><img id="tXeeBti6hHdSxbUg9p98Q8" name="91THUOGoGLL._AC_SL1500_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/tXeeBti6hHdSxbUg9p98Q8-1920-80.jpg" mos="" align="middle" fullscreen="" width="1447" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Morvat-Organizer-Accessories-Organize-Equipment/dp/B0799QHWF6/" target="_blank" rel="nofollow" data-dimension112="5595dee6-cee7-11f1-b1d4-d39090d8916e" data-action="Deal Block" data-label="Golf Organizer" data-dimension48="Golf Organizer" data-dimension25="$59">Golf Organizer: $59</a></strong><br />Do you know a golfer with so much equipment that they can't organize it? Then this budget-friendly golf bag organizer is a must. It's designed to hold two bags and has shelves for the rest of the golfer's gear, like their shoes, balls and everything else. Just be sure they have the space for this before buying.<a class="view-deal button" href="https://www.amazon.com/Morvat-Organizer-Accessories-Organize-Equipment/dp/B0799QHWF6/" target="_blank" rel="nofollow" data-dimension112="5595dee6-cee7-11f1-b1d4-d39090d8916e" data-action="Deal Block" data-label="Golf Organizer" data-dimension48="Golf Organizer" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="5595df54-cee7-11f1-893c-5f7074aab882" data-action="Deal Block" data-label="Headcover" data-dimension48="Headcover" data-dimension25="$" href="https://pinsandaces.com/collections/headcovers" 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:125.00%;"><img id="BF97sXJr8AbxQdcmpgt2mg" name="image" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/BF97sXJr8AbxQdcmpgt2mg-1920-80.png" mos="" align="middle" fullscreen="" width="600" height="750" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>Every golfer needs headcovers to protect their woods, hybrids and putter, so getting a stylish, themed one from Pins &amp; Aces is a perfect gift. The company makes some of the most fabulous headcovers on the market, and you can choose from a variety to suit the tastes of the person you're shopping for (there are a ton of options, from licensed brands to original designs).<a class="view-deal button" href="https://pinsandaces.com/collections/headcovers" target="_blank" rel="nofollow" data-dimension112="5595df54-cee7-11f1-893c-5f7074aab882" data-action="Deal Block" data-label="Headcover" data-dimension48="Headcover" data-dimension25="$">View Deal</a></p></div><div class="product"><a data-dimension112="5595dfc2-cee7-11f1-80d2-eb5d0ce750fc" data-action="Deal Block" data-label="Player V Pro" data-dimension48="Player V Pro" data-dimension25="$489" href="https://vesselgolf.com/products/player-v-pro-stand" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1200px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="G2LsbYrPqZmrTngEHUqzub" name="Player V Pro" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/G2LsbYrPqZmrTngEHUqzub-1920-80.png" mos="" align="middle" fullscreen="" width="1200" height="1200" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>To me, Vessel bags epitomize golf luxury. The Player V Pro was the best golf bag I've ever used, but the <a href="https://vesselgolf.com/products/player-vi-pro-stand" target="_blank" rel="nofollow" data-dimension112="5595dfc2-cee7-11f1-80d2-eb5d0ce750fc" data-action="Deal Block" data-label="Player V Pro" data-dimension48="Player V Pro" data-dimension25="$489">Player VI Pro</a> has surpassed it. However, if you want to get a tremendous bag for a little less, I can still easily recommend the Player V Pro! I even had the chance to <a href="https://www.tomsguide.com/wellness/fitness/i-think-we-may-have-the-biggest-market-share-on-tour-vessel-golfs-ceo-and-players-use-the-bags-by-choice">talk to Vessel's CEO</a> about what makes the bags so good.<a class="view-deal button" href="https://vesselgolf.com/products/player-v-pro-stand" target="_blank" rel="nofollow" data-dimension112="5595dfc2-cee7-11f1-80d2-eb5d0ce750fc" data-action="Deal Block" data-label="Player V Pro" data-dimension48="Player V Pro" data-dimension25="$489">View Deal</a></p></div><div class="product"><a data-dimension112="5595e030-cee7-11f1-8311-77ba8d3a8482" data-action="Deal Block" data-label="AI Navigator GPS+ Electric Caddy" data-dimension48="AI Navigator GPS+ Electric Caddy" data-dimension25="$1895" href="https://www.pgatoursuperstore.com/ai-navigator-gps-electric-caddy/2000000043838.html?dwvar_2000000043838_STK_COLOR=5&amp;cgid=golf-bags-carts-ppcart-electric" 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="wuf9d8NExMGrYzZRy4D6H9" name="AI Navigator GPS+ Electric Caddy" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/wuf9d8NExMGrYzZRy4D6H9-1920-80.png" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.pgatoursuperstore.com/ai-navigator-gps-electric-caddy/2000000043838.html?dwvar_2000000043838_STK_COLOR=5&amp;cgid=golf-bags-carts-ppcart-electric" target="_blank" rel="nofollow" data-dimension112="5595e030-cee7-11f1-8311-77ba8d3a8482" data-action="Deal Block" data-label="AI Navigator GPS+ Electric Caddy" data-dimension48="AI Navigator GPS+ Electric Caddy" data-dimension25="$1895">AI Navigator GPS+ Electric Caddy: $1895</a></strong><br />Okay, so this isn't your typical golf gift, as it's super expensive, but if you have a hefty budget and want a gift that most golfers will want but might not want to buy themselves, this is the electric push cart I use to golf every week. Between the rugged, all-terrain design, the GPS screen and all the other well-appointed features, this is the premium gift for any occasion.<a class="view-deal button" href="https://www.pgatoursuperstore.com/ai-navigator-gps-electric-caddy/2000000043838.html?dwvar_2000000043838_STK_COLOR=5&amp;cgid=golf-bags-carts-ppcart-electric" target="_blank" rel="nofollow" data-dimension112="5595e030-cee7-11f1-8311-77ba8d3a8482" data-action="Deal Block" data-label="AI Navigator GPS+ Electric Caddy" data-dimension48="AI Navigator GPS+ Electric Caddy" data-dimension25="$1895">View Deal</a></p></div><h3 class="article-body__section" id="section-golf-gadgets"><span>Golf Gadgets</span></h3><div class="product"><a data-dimension112="5595e116-cee7-11f1-8206-29eedd84ca7d" data-action="Deal Block" data-label="Magnetic Golf Cart Phone Holder" data-dimension48="Magnetic Golf Cart Phone Holder" data-dimension25="$16" href="https://www.amazon.com/Dual-Sided-Magnetic-Holder-Rotatable-Accessories/dp/B0GTLSVQGP" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1300px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="ZzDmKQtMQgWzraDUJzpfY5" name="Magnetic Golf Cart Phone Holder" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZzDmKQtMQgWzraDUJzpfY5-1920-80.png" mos="" align="middle" fullscreen="" width="1300" height="1300" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Dual-Sided-Magnetic-Holder-Rotatable-Accessories/dp/B0GTLSVQGP" target="_blank" rel="nofollow" data-dimension112="5595e116-cee7-11f1-8206-29eedd84ca7d" data-action="Deal Block" data-label="Magnetic Golf Cart Phone Holder" data-dimension48="Magnetic Golf Cart Phone Holder" data-dimension25="$16">Magnetic Golf Cart Phone Holder: was $20 now $16</a></strong><br />This is a cool gift for the golfer who uses their phone as an on-course GPS device (and has a magnetic phone or case). This gives them a great place to put their phone without having to carry it around in their pocket all round.<a class="view-deal button" href="https://www.amazon.com/Dual-Sided-Magnetic-Holder-Rotatable-Accessories/dp/B0GTLSVQGP" target="_blank" rel="nofollow" data-dimension112="5595e116-cee7-11f1-8206-29eedd84ca7d" data-action="Deal Block" data-label="Magnetic Golf Cart Phone Holder" data-dimension48="Magnetic Golf Cart Phone Holder" data-dimension25="$16">View Deal</a></p></div><div class="product"><a data-dimension112="5595e184-cee7-11f1-b20d-c77785fd792f" data-action="Deal Block" data-label="Pop Up Golf Chipping Net" data-dimension48="Pop Up Golf Chipping Net" data-dimension25="$25" href="https://www.amazon.com/Rolilac-Pop-Golf-Chipping-Net/dp/B07GLY5NQQ/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:982px;"><p class="vanilla-image-block" style="padding-top:82.69%;"><img id="FgjnAmmyrjAcvh3oMTGarK" name="71kT3myQjxL._AC_SL1000_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/FgjnAmmyrjAcvh3oMTGarK-1920-80.jpg" mos="" align="middle" fullscreen="" width="982" height="812" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Rolilac-Pop-Golf-Chipping-Net/dp/B07GLY5NQQ/" target="_blank" rel="nofollow" data-dimension112="5595e184-cee7-11f1-b20d-c77785fd792f" data-action="Deal Block" data-label="Pop Up Golf Chipping Net" data-dimension48="Pop Up Golf Chipping Net" data-dimension25="$25">Pop Up Golf Chipping Net: $25</a></strong><br />This portable one is hard to beat for the golfer who would enjoy a simple practice net. It can be used indoors and outdoors to practice chipping, with multiple pockets to hone accuracy and aim. Rounds are won and lost around the greens; this practice tool can make a difference.<a class="view-deal button" href="https://www.amazon.com/Rolilac-Pop-Golf-Chipping-Net/dp/B07GLY5NQQ/" target="_blank" rel="nofollow" data-dimension112="5595e184-cee7-11f1-b20d-c77785fd792f" data-action="Deal Block" data-label="Pop Up Golf Chipping Net" data-dimension48="Pop Up Golf Chipping Net" data-dimension25="$25">View Deal</a></p></div><div class="product"><a data-dimension112="5595e1f2-cee7-11f1-b7f2-15cd8018eb00" data-action="Deal Block" data-label="Golf Swing Trainer Aid" data-dimension48="Golf Swing Trainer Aid" data-dimension25="$40" href="https://www.amazon.com/Amazon-Basics-Golf-Swing-Trainer/dp/B09N3HZK2J" 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:98.87%;"><img id="DTkVcYRPfV6Jt7kQwus6oZ" name="image" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/DTkVcYRPfV6Jt7kQwus6oZ-1920-80.png" mos="" align="middle" fullscreen="" width="1500" height="1483" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Amazon-Basics-Golf-Swing-Trainer/dp/B09N3HZK2J" target="_blank" rel="nofollow" data-dimension112="5595e1f2-cee7-11f1-b7f2-15cd8018eb00" data-action="Deal Block" data-label="Golf Swing Trainer Aid" data-dimension48="Golf Swing Trainer Aid" data-dimension25="$40">Golf Swing Trainer Aid: $40</a></strong><br />Golfers can spend their entire lives mastering their swing, but a trusted accessory for practicing swing sequencing and tempo is a swing trainer like this one. It fits in a golf bag, so golfers can warm up even on the course, as the extra weight helps get the blood flowing, allowing for a looser, more confident swing.<a class="view-deal button" href="https://www.amazon.com/Amazon-Basics-Golf-Swing-Trainer/dp/B09N3HZK2J" target="_blank" rel="nofollow" data-dimension112="5595e1f2-cee7-11f1-b7f2-15cd8018eb00" data-action="Deal Block" data-label="Golf Swing Trainer Aid" data-dimension48="Golf Swing Trainer Aid" data-dimension25="$40">View Deal</a></p></div><div class="product"><a data-dimension112="5595e260-cee7-11f1-b9cd-bb07a5750ff0" data-action="Deal Block" data-label="Putting Mat" data-dimension48="Putting Mat" data-dimension25="$69" href="https://www.amazon.com/CHAMPKEY-Premium-Wooden-Putting-Gates/dp/B0CSPQGX2Y" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1356px;"><p class="vanilla-image-block" style="padding-top:110.62%;"><img id="uUbhMJ8As7f4gCQ6heXuJn" name="81VLGD7Bx0L._AC_SL1500_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/uUbhMJ8As7f4gCQ6heXuJn-1920-80.jpg" mos="" align="middle" fullscreen="" width="1356" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>Yes, golfers <em>do</em> need dedicated training tools for each golf skill. So, if they don't already have a putting mat, this roll-up one would make a great gift. Measuring 10 feet, this training mat can help golfers master their putts, and it even comes with gates to help take the practice up a notch.<a class="view-deal button" href="https://www.amazon.com/CHAMPKEY-Premium-Wooden-Putting-Gates/dp/B0CSPQGX2Y" target="_blank" rel="nofollow" data-dimension112="5595e260-cee7-11f1-b9cd-bb07a5750ff0" data-action="Deal Block" data-label="Putting Mat" data-dimension48="Putting Mat" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="5595e2ce-cee7-11f1-8020-f91e9f108030" data-action="Deal Block" data-label="Complete System" data-dimension48="Complete System" data-dimension25="$175" href="https://pathpalgolf.com/pages/complete-training-package" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1280px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="yB4gvNi4hKZEw5RHeR54f" name="pathpal-white" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/yB4gvNi4hKZEw5RHeR54f-1920-80.jpg" mos="" align="middle" fullscreen="" width="1280" height="1280" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>I've talked before about how much <a href="https://www.tomsguide.com/wellness/fitness/stop-wasting-money-on-a-new-driver-every-year-get-this-simple-training-aid-instead" data-dimension112="5595e2ce-cee7-11f1-8020-f91e9f108030" data-action="Deal Block" data-label="Complete System" data-dimension48="Complete System" data-dimension25="$175">PathPal helped me improve my slice</a>, and I can't recommend this product enough. The complete system comes with all the pieces you need to improve your swing path and get better at golf. Is there a better gift for the golfer in your life than an improved swing? Better swing = more fun. <a class="view-deal button" href="https://pathpalgolf.com/pages/complete-training-package" target="_blank" rel="nofollow" data-dimension112="5595e2ce-cee7-11f1-8020-f91e9f108030" data-action="Deal Block" data-label="Complete System" data-dimension48="Complete System" data-dimension25="$175">View Deal</a></p></div><div class="product"><a data-dimension112="5595e60c-cee7-11f1-9a05-b1da21a2630d" data-action="Deal Block" data-label="Sensor 4" data-dimension48="Sensor 4" data-dimension25="$345" href="https://hackmotion.com/hackmotion-sensor-4/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:200px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="LMgvQfbLfbhtcrDihEYTnE" name="image" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/LMgvQfbLfbhtcrDihEYTnE-1920-80.png" mos="" align="middle" fullscreen="" width="200" height="200" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://hackmotion.com/hackmotion-sensor-4/" target="_blank" rel="nofollow" data-dimension112="5595e60c-cee7-11f1-9a05-b1da21a2630d" data-action="Deal Block" data-label="Sensor 4" data-dimension48="Sensor 4" data-dimension25="$345">Sensor 4: $345</a></strong><br />I've spent the last few months practicing with HackMotion's wrist-based training tool, the <a href="https://hackmotion.com/hackmotion-sensor-3/" target="_blank" rel="nofollow">Sensor 3</a>, and I'm constantly blown away by how much you can learn about your golf swing just from your wrist angles. I've noticeably improved both my ball striking and tee shots since using this fancy golf tech, and I can't imagine practicing without it.<a class="view-deal button" href="https://hackmotion.com/hackmotion-sensor-4/" target="_blank" rel="nofollow" data-dimension112="5595e60c-cee7-11f1-9a05-b1da21a2630d" data-action="Deal Block" data-label="Sensor 4" data-dimension48="Sensor 4" data-dimension25="$345">View Deal</a></p></div><div class="product"><a data-dimension112="5595e698-cee7-11f1-938a-0577624049ba" data-action="Deal Block" data-label="Air" data-dimension48="Air" data-dimension25="$349" href="https://www.arccosgolf.com/pages/us-air-sl" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="B6KJ7gsv8Nqxiqc8QhfmdY" name="Air" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/B6KJ7gsv8Nqxiqc8QhfmdY-1920-80.png" mos="" align="middle" fullscreen="" width="1800" height="1800" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>For my money, no product on the golf market beats Arccos. Since I started golfing, I've tracked my game with the <a href="https://www.arccosgolf.com/products/smart-sensors" target="_blank" data-dimension112="5595e698-cee7-11f1-938a-0577624049ba" data-action="Deal Block" data-label="Air" data-dimension48="Air" data-dimension25="$349">club sensors</a>, and now the company offers the Air, which provides the same level of tracking without anything on the clubs. If the golfer you love is looking to improve their game, this is the gift to buy.<a class="view-deal button" href="https://www.arccosgolf.com/pages/us-air-sl" target="_blank" rel="nofollow" data-dimension112="5595e698-cee7-11f1-938a-0577624049ba" data-action="Deal Block" data-label="Air" data-dimension48="Air" data-dimension25="$349">View Deal</a></p></div><div class="product"><a data-dimension112="5595e706-cee7-11f1-995c-6b980055cb29" data-action="Deal Block" data-label="Approach R10" data-dimension48="Approach R10" data-dimension25="$499" href="https://www.amazon.com/Garmin-Approach-Portable-Monitor-Indoors/dp/B095QX1FSR" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1470px;"><p class="vanilla-image-block" style="padding-top:102.04%;"><img id="PkuskGztGMrF4kpQkN95nF" name="61POLvv99xS._AC_SL1500_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/PkuskGztGMrF4kpQkN95nF-1920-80.jpg" mos="" align="middle" fullscreen="" width="1470" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The <a href="https://www.tomsguide.com/Garmin-approach-R10-review" data-dimension112="5595e706-cee7-11f1-995c-6b980055cb29" data-action="Deal Block" data-label="Approach R10" data-dimension48="Approach R10" data-dimension25="$499">Garmin Approach R10</a> golf launch monitor is a tremendous big-ticket gift for the golfer looking to measure their game. This clever gadget analyzes swings and shots to offer guidance in a companion app, and it even works as a complete golf simulator. Compared with others on the market, it's very reasonably priced, making it a good gift.<a class="view-deal button" href="https://www.amazon.com/Garmin-Approach-Portable-Monitor-Indoors/dp/B095QX1FSR" target="_blank" rel="nofollow" data-dimension112="5595e706-cee7-11f1-995c-6b980055cb29" data-action="Deal Block" data-label="Approach R10" data-dimension48="Approach R10" data-dimension25="$499">View Deal</a></p></div><div class="product"><a data-dimension112="805b5466-d38e-11f1-be8f-d91764ba5f0a" data-action="Deal Block" data-label="Approach S72" data-dimension48="Approach S72" data-dimension25="$799" href="https://www.garmin.com/en-US/p/1937140/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1490px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="EE5wYJphQpkqPstx5iSizN" name="Approach S72" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/EE5wYJphQpkqPstx5iSizN-1920-80.png" mos="" align="middle" fullscreen="" width="1490" height="1490" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.garmin.com/en-US/p/1937140/" target="_blank" rel="nofollow" data-dimension112="805b5466-d38e-11f1-be8f-d91764ba5f0a" data-action="Deal Block" data-label="Approach S72" data-dimension48="Approach S72" data-dimension25="$799">Approach S72: $799</a></strong><br />This Garmin smartwatch has more features than any other golf watch on the market, and it's no contest. I started using it, and I'm blown away. It has wrist sensing, which is perfect for the driving range. It also helps with green reading, lets you see how your heart rate affects your golf performance and offers maps, scoring and more. It's expensive, but for the features, it doesn't feel overpriced. <a class="view-deal button" href="https://www.garmin.com/en-US/p/1937140/" target="_blank" rel="nofollow" data-dimension112="805b5466-d38e-11f1-be8f-d91764ba5f0a" data-action="Deal Block" data-label="Approach S72" data-dimension48="Approach S72" data-dimension25="$799">View Deal</a></p></div><h3 class="article-body__section" id="section-off-course-golf-gifts"><span>Off-Course Golf Gifts</span></h3><div class="product"><a data-dimension112="5595e7d8-cee7-11f1-93aa-27a04ca61e8b" data-action="Deal Block" data-label="Golfer's Scratch Off Poster" data-dimension48="Golfer's Scratch Off Poster" data-dimension25="$25" href="https://www.uncommongoods.com/product/golfers-scratch-off-poster" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="xxLsMrXyZxsrKd5M7Hei4F" name="courses.png" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/xxLsMrXyZxsrKd5M7Hei4F-1920-80.png" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.uncommongoods.com/product/golfers-scratch-off-poster" target="_blank" rel="nofollow" data-dimension112="5595e7d8-cee7-11f1-93aa-27a04ca61e8b" data-action="Deal Block" data-label="Golfer's Scratch Off Poster" data-dimension48="Golfer's Scratch Off Poster" data-dimension25="$25">Golfer's Scratch Off Poster: $25</a></strong><br />If you know a golfer who travels to play famous courses, this scratch-off poster from Uncommon Goods is a thoughtful gift idea. This way, they can keep track of where they've played and where they should book a trip to next.<a class="view-deal button" href="https://www.uncommongoods.com/product/golfers-scratch-off-poster" target="_blank" rel="nofollow" data-dimension112="5595e7d8-cee7-11f1-93aa-27a04ca61e8b" data-action="Deal Block" data-label="Golfer's Scratch Off Poster" data-dimension48="Golfer's Scratch Off Poster" data-dimension25="$25">View Deal</a></p></div><div class="product"><a data-dimension112="5595e83c-cee7-11f1-bf96-b9633b57e35f" data-action="Deal Block" data-label="Nextgen Den Caddy" data-dimension48="Nextgen Den Caddy" data-dimension25="$105" href="https://www.pxg.com/products/nextgen-den-caddy" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1440px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="RuCWdBXEop2ZpzQAKN44XX" name="Nextgen Den Caddy" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/RuCWdBXEop2ZpzQAKN44XX-1920-80.png" mos="" align="middle" fullscreen="" width="1440" height="1440" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.pxg.com/products/nextgen-den-caddy" target="_blank" rel="nofollow" data-dimension112="5595e83c-cee7-11f1-bf96-b9633b57e35f" data-action="Deal Block" data-label="Nextgen Den Caddy" data-dimension48="Nextgen Den Caddy" data-dimension25="$105">Nextgen Den Caddy: $105</a></strong><br />A den caddy is a fun thing to have around the house for storing clubs, balls or just about anything else. It's like a mini golf bag that happens to look cool. I have a PXG den caddy in my simulator for storing my various training aids (some of which are outlined above), but it's just a cool accessory to have around, and at $105, PXG's is one of the more reasonably priced options.<a class="view-deal button" href="https://www.pxg.com/products/nextgen-den-caddy" target="_blank" rel="nofollow" data-dimension112="5595e83c-cee7-11f1-bf96-b9633b57e35f" data-action="Deal Block" data-label="Nextgen Den Caddy" data-dimension48="Nextgen Den Caddy" data-dimension25="$105">View Deal</a></p></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness/stop-buying-awful-golf-gifts-21-things-all-obsessed-golfers-actually-want</link>
                                                                            <description>
                            <![CDATA[ Here are the best gifts for golfers from top-rated golf brands, plus some fun gifts most golfers don't have. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">h3x7wRkM2QZj2PToUshJFH</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/sBpkYtusSbApEpcdB6fYAm-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 23 Oct 2026 13:40:37 +0000</pubDate>                                                                                                                                <updated>Sat, 31 Oct 2026 01:47:09 +0000</updated>
                                                                                                                                            <category><![CDATA[Fitness]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                <author><![CDATA[ dave.leclair@futurenet.com (Dave LeClair) ]]></author>                    <dc:creator><![CDATA[ Dave LeClair ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/fyx7qYdxPMTNBhdnMfNmaB-320-70.png ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Dave LeClair is the Managing News Editor for Tom&#039;s Guide, keeping his finger on the pulse of all things technology. He loves taking the complicated happenings in the tech world and explaining why they matter. Whether Apple is announcing the next big thing in the mobile space or a small startup advancing generative AI, Dave will apply his experience to help you figure out what&#039;s happening and why it&#039;s relevant to your life.&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;Before Tom&#039;s Guide, Dave worked for publications like PCMag, Pocket-lint, MUO, How-To Geek, Digital Trends, and others. He started writing about technology professionally for MUO in 2011 and hasn&#039;t looked back since. In addition to news, you can find reviews, how-to pieces, shopping guides, and many other types of content with Dave&#039;s name attached.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/sBpkYtusSbApEpcdB6fYAm-1920-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Golfers fist bumping]]></media:description>                                                            <media:text><![CDATA[Golfers fist bumping]]></media:text>
                                <media:title type="plain"><![CDATA[Golfers fist bumping]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/sBpkYtusSbApEpcdB6fYAm-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I am obsessed with golf. I am also addicted to golf equipment and apparel. I also love shopping for friends and loved ones (and myself), so I figured, why not combine those passions and round up the best golf gifts for any time of year? </p><p>Over the years, <strong>I've tested hundreds of golf products</strong>. I've played with the best <a href="https://www.tomsguide.com/wellness/smartwatches/i-tested-the-3-best-golf-apps-for-apple-watch-heres-my-favorite">game-tracking tool, Arccos</a>, and I've tried some <a href="https://www.tomsguide.com/wellness/fitness/stop-wasting-money-on-a-new-driver-every-year-get-this-simple-training-aid-insteadhttps://www.tomsguide.com/wellness/fitness/ive-been-golfing-for-4-years-and-these-are-the-gadgets-that-helped-me-improve">cool training aids</a>. I've used <a href="https://www.tomsguide.com/wellness/fitness/sick-of-your-golf-bag-looking-boring-i-tried-two-you-can-customize">custom golf bags</a> and <a href="https://www.tomsguide.com/wellness/fitness/foresight-gc3-launch-monitor-6-month-impressions">high-end launch monitors</a>. </p><p>I've seen it all and tried most of it (and yet I'm still not very good at golf, which proves two things: golf is hard, and equipment doesn't automatically make you good). </p><p>I've created the<strong> ultimate list of gifts for the golf lover in your life, including options for every budget</strong>. I could have included way more products, but I kept it to a manageable list of things I actually use (or would happily receive as a gift) so you can be confident you're getting something they'll like.</p><p>I <strong>didn't include highly preference-based products</strong>, especially for experienced golfers. </p><p>For example, you won't find golf balls on the list, as serious golfers typically have one ball they play, and unless you know which one it is, balls are almost guaranteed to be returned. The same goes for clubs — many golfers get fitted for the right clubs, so buying them a random 5-wood won't do the job. </p><p>Instead, we're <strong>focused on useful items </strong>golfers might not have that<strong> aren't custom or tied to specific preferences.</strong></p><p>Does that mean you can't buy balls or clubs if you know what to get? Of course not. If you know your favorite golfer plays <a href="https://www.amazon.com/Titleist-Pro-V1-2025/dp/B0DPN7QZ9R" target="_blank" rel="nofollow">Titleist Pro V1</a> or <a href="https://www.amazon.com/VICE-Drip-Version-Balls-Black/dp/B08SR9ZLSY" target="_blank" rel="nofollow">Vice Pro</a> (my golf ball of choice), for example, then by all means grab them a dozen balls and call it a day! </p><h3 class="article-body__section" id="section-quick-links-my-top-5-gifts-for-golfers"><span>Quick Links: My top 5 gifts for golfers</span></h3><ol start="1"><li><strong></strong><a href="https://www.arccosgolf.com/pages/us-air-sl" target="_blank" rel="nofollow"><strong>Arccos Air game tracking system</strong></a><strong></strong></li><li><strong></strong><a href="https://pathpalgolf.com/pages/complete-training-package" target="_blank" rel="nofollow"><strong>PathPal training aid</strong></a><strong></strong></li><li><a href="https://www.quince.com/shop/activewear/shop-by-activity/mens-golf" target="_blank" rel="nofollow"><strong>Quince affordable golf apparel</strong></a></li><li><a href="https://hackmotion.com/hackmotion-sensor-4/" target="_blank" rel="nofollow"><strong>HackMotion Sensor 4</strong></a></li><li><strong></strong><a href="https://vesselgolf.com/products/player-v-pro-stand-eden" target="_blank" rel="nofollow"><strong>Vessel Golf Player V Pro stand bag</strong></a><strong></strong></li></ol><h3 class="article-body__section" id="section-golf-apparel"><span>Golf apparel</span></h3><div class="product"><a data-dimension112="5595db6c-cee7-11f1-be82-93287409d51a" data-action="Deal Block" data-label="Quince Golf apparel: starting at $29" data-dimension48="Quince Golf apparel: starting at $29" href="https://www.quince.com/shop/activewear/shop-by-activity/mens-golf" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:399px;"><p class="vanilla-image-block" style="padding-top:125.56%;"><img id="78FdcUTCg7ciEJsjfamBbH" name="Quincepants" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/78FdcUTCg7ciEJsjfamBbH-1920-80.png" mos="" align="middle" fullscreen="" width="399" height="501" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><a href="https://www.quince.com/shop/activewear/shop-by-activity/mens-golf?sortBy=PRICE_LOW_TO_HIGH" target="_blank" rel="nofollow" data-dimension112="5595db6c-cee7-11f1-be82-93287409d51a" data-action="Deal Block" data-label="Quince Golf apparel: starting at $29" data-dimension48="Quince Golf apparel: starting at $29" data-dimension25=""><strong>Quince Golf apparel: starting at $29</strong></a><br />Golf clothing is usually quite expensive. Most of my favorite pieces are $90 or more. But Quince is setting out to disrupt the trend by offering nice clothing at affordable prices. I tried <a href="https://www.quince.com/men/protech-golf-pants?color=riviera-blue" target="_blank" rel="nofollow">Quince golf pants</a>, a <a href="https://www.quince.com/men/recycled-flowknit-performance-polo?color=olive&amp;gender=men&amp;size=xl" target="_blank" rel="nofollow">comfy polo</a> and more and found them to be on the same level of comfort as stuff from more expensive brands. They're a great gift because you don't need to spend tons of money to get stylish, comfortable golf clothing for the player in your life.<a class="view-deal button" href="https://www.quince.com/shop/activewear/shop-by-activity/mens-golf" target="_blank" rel="nofollow" data-dimension112="5595db6c-cee7-11f1-be82-93287409d51a" data-action="Deal Block" data-label="Quince Golf apparel: starting at $29" data-dimension48="Quince Golf apparel: starting at $29" data-dimension25="">View Deal</a></p></div><div class="product"><a data-dimension112="5595dbda-cee7-11f1-a76f-915c31fabff3" data-action="Deal Block" data-label="3-Pack Golf Web Belt" data-dimension48="3-Pack Golf Web Belt" data-dimension25="$17" href="https://www.amazon.com/Nike-Mens-Pack-White-Gray/dp/B004NRNOG8" 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:108.25%;"><img id="brpVgfiASDYCT3oYqfMCiT" name="71H621JjWtL._AC_SX679_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/brpVgfiASDYCT3oYqfMCiT-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="735" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nike-Mens-Pack-White-Gray/dp/B004NRNOG8" target="_blank" rel="nofollow" data-dimension112="5595dbda-cee7-11f1-a76f-915c31fabff3" data-action="Deal Block" data-label="3-Pack Golf Web Belt" data-dimension48="3-Pack Golf Web Belt" data-dimension25="$17">3-Pack Golf Web Belt: was $24 now $17</a></strong><br />Good belts are a must for golf attire, and our favorite value option is these stretchy Nike belts. This three-pack makes a great gift for golfers, considering it's one of those things you can never have enough of. Having color options allows golfers to complete their outfits, as the belt is often the finishing touch to a style.<a class="view-deal button" href="https://www.amazon.com/Nike-Mens-Pack-White-Gray/dp/B004NRNOG8" target="_blank" rel="nofollow" data-dimension112="5595dbda-cee7-11f1-a76f-915c31fabff3" data-action="Deal Block" data-label="3-Pack Golf Web Belt" data-dimension48="3-Pack Golf Web Belt" data-dimension25="$17">View Deal</a></p></div><div class="product"><a data-dimension112="5595dc48-cee7-11f1-8e38-49873a24b8e8" data-action="Deal Block" data-label="Braided Belt" data-dimension48="Braided Belt" data-dimension25="$49" href="https://thebyrd.com/products/the-braided-byrd-golf-belt-black-capped-chickadee" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:476px;"><p class="vanilla-image-block" style="padding-top:141.18%;"><img id="suZWaqKcciv8MbdqmJrErQ" name="Braided Belt" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/suZWaqKcciv8MbdqmJrErQ-1920-80.png" mos="" align="middle" fullscreen="" width="476" height="672" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://thebyrd.com/products/the-braided-byrd-golf-belt-black-capped-chickadee" target="_blank" rel="nofollow" data-dimension112="5595dc48-cee7-11f1-8e38-49873a24b8e8" data-action="Deal Block" data-label="Braided Belt" data-dimension48="Braided Belt" data-dimension25="$49">Braided Belt: was $55 now $49</a></strong><br />On the course, golfers need to carry a divot tool, ball marker, tees, balls and anything else they need to make their round enjoyable. The Byrd Belt is a fun gift that turns many of those products into a belt. And it's a nice belt that I wear off the course just as much as on it.<a class="view-deal button" href="https://thebyrd.com/products/the-braided-byrd-golf-belt-black-capped-chickadee" target="_blank" rel="nofollow" data-dimension112="5595dc48-cee7-11f1-8e38-49873a24b8e8" data-action="Deal Block" data-label="Braided Belt" data-dimension48="Braided Belt" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="805b5326-d38e-11f1-a50c-cda0970364f8" data-action="Deal Block" data-label="Cotton Stretch Belt" data-dimension48="Cotton Stretch Belt" data-dimension25="$138" href="https://www.johnnie-o.com/products/jmbl1510-cotton-stretch-belt-azalea" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1200px;"><p class="vanilla-image-block" style="padding-top:125.00%;"><img id="uw74fjXmXFi5y3rDd7gA6P" name="Cotton Stretch Belt" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/uw74fjXmXFi5y3rDd7gA6P-1920-80.png" mos="" align="middle" fullscreen="" width="1200" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.johnnie-o.com/products/jmbl1510-cotton-stretch-belt-azalea" target="_blank" rel="nofollow" data-dimension112="805b5326-d38e-11f1-a50c-cda0970364f8" data-action="Deal Block" data-label="Cotton Stretch Belt" data-dimension48="Cotton Stretch Belt" data-dimension25="$138">Cotton Stretch Belt: $138</a></strong><br />Okay, so this belt is rather expensive, but I'm not kidding when I say it's the best belt I've ever owned. It fits perfectly, stretches well and comes in vibrant colors that complete any outfit. A pop of color could be exactly what the golfer in your life needs, and this belt delivers.<a class="view-deal button" href="https://www.johnnie-o.com/products/jmbl1510-cotton-stretch-belt-azalea" target="_blank" rel="nofollow" data-dimension112="805b5326-d38e-11f1-a50c-cda0970364f8" data-action="Deal Block" data-label="Cotton Stretch Belt" data-dimension48="Cotton Stretch Belt" data-dimension25="$138">View Deal</a></p></div><h3 class="article-body__section" id="section-golf-accessories"><span>Golf Accessories</span></h3><div class="product"><a data-dimension112="5595dd2e-cee7-11f1-aba9-ffa42f4dfc82" data-action="Deal Block" data-label="Odyssey Putt Target" data-dimension48="Odyssey Putt Target" data-dimension25="$8" href="https://www.pgatoursuperstore.com/odyssey-putt-target/1018975.html?cgid=golf-accessories-training-aids" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="2vAvha7DKVgfkaEV6A7ofg" name="Odyssey Putt Target" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/2vAvha7DKVgfkaEV6A7ofg-1920-80.png" mos="" align="middle" fullscreen="" width="500" height="500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.pgatoursuperstore.com/odyssey-putt-target/1018975.html?cgid=golf-accessories-training-aids" target="_blank" rel="nofollow" data-dimension112="5595dd2e-cee7-11f1-aba9-ffa42f4dfc82" data-action="Deal Block" data-label="Odyssey Putt Target" data-dimension48="Odyssey Putt Target" data-dimension25="$8">Odyssey Putt Target: $8</a></strong><br />This is the perfect gift for the golfer who seemingly has everything. It's a putting target the size of a golf hole, so when the putting green is busy and all the holes are taken, they can throw this down and get their warm-up putts in. It's thoughtful and cheap — two of my favorite elements of any gift.<a class="view-deal button" href="https://www.pgatoursuperstore.com/odyssey-putt-target/1018975.html?cgid=golf-accessories-training-aids" target="_blank" rel="nofollow" data-dimension112="5595dd2e-cee7-11f1-aba9-ffa42f4dfc82" data-action="Deal Block" data-label="Odyssey Putt Target" data-dimension48="Odyssey Putt Target" data-dimension25="$8">View Deal</a></p></div><div class="product"><a data-dimension112="fc108c40-d4cc-11f1-84ea-533589136996" data-action="Deal Block" data-label="Pro Splash Brush" data-dimension48="Pro Splash Brush" data-dimension25="$25" href="https://www.pgatoursuperstore.com/pro-caddy-splash-brush/1178594001.html" 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="YL55cSjYnsYxtBgMzY6jEN" name="Pro Splash Brush" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/YL55cSjYnsYxtBgMzY6jEN-1920-80.png" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.pgatoursuperstore.com/pro-caddy-splash-brush/1178594001.html" target="_blank" rel="nofollow" data-dimension112="fc108c40-d4cc-11f1-84ea-533589136996" data-action="Deal Block" data-label="Pro Splash Brush" data-dimension48="Pro Splash Brush" data-dimension25="$25">Pro Splash Brush: $25</a></strong><br />No one likes dirty golf clubs, and the Caddy Splash Pro is the best way I've found to keep them clean. I never play a round without one clipped to my bag (I used to roll with the <a href="https://www.pgatoursuperstore.com/original-caddy-splash-brush/2000000054572.html" target="_blank" rel="nofollow">original Caddy Splash</a>, but I've since upgraded to this one).<a class="view-deal button" href="https://www.pgatoursuperstore.com/pro-caddy-splash-brush/1178594001.html" target="_blank" rel="nofollow" data-dimension112="fc108c40-d4cc-11f1-84ea-533589136996" data-action="Deal Block" data-label="Pro Splash Brush" data-dimension48="Pro Splash Brush" data-dimension25="$25">View Deal</a></p></div><div class="product"><a data-dimension112="5595dd9c-cee7-11f1-a1d7-5350f755f5ef" data-action="Deal Block" data-label="Magnetic Towel" data-dimension48="Magnetic Towel" data-dimension25="$30" href="https://ghostgolf.com/collections/towels/products/magnetic-towel-greenside" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="NqKhij8fZ47hpCeqjJpSP4" name="golf towel.png" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/NqKhij8fZ47hpCeqjJpSP4-1920-80.png" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://ghostgolf.com/collections/towels/products/magnetic-towel-greenside" target="_blank" rel="nofollow" data-dimension112="5595dd9c-cee7-11f1-a1d7-5350f755f5ef" data-action="Deal Block" data-label="Magnetic Towel" data-dimension48="Magnetic Towel" data-dimension25="$30">Magnetic Towel: $30</a></strong><br />Another piece of equipment a golfer can never have enough of is a fresh golf towel for their bag. We like this magnetic one that can be picked up off the ground quickly with a club and has plenty of great color options. Ghost Golf has quickly risen to become one of the most popular brands, and it's largely thanks to making high-quality gear.<a class="view-deal button" href="https://ghostgolf.com/collections/towels/products/magnetic-towel-greenside" target="_blank" rel="nofollow" data-dimension112="5595dd9c-cee7-11f1-a1d7-5350f755f5ef" data-action="Deal Block" data-label="Magnetic Towel" data-dimension48="Magnetic Towel" data-dimension25="$30">View Deal</a></p></div><div class="product"><a data-dimension112="5595de0a-cee7-11f1-a203-cd3ca1ab7d84" data-action="Deal Block" data-label="2 Layer Golf Trunk Organizer" data-dimension48="2 Layer Golf Trunk Organizer" data-dimension25="$32" href="https://www.amazon.com/Organizer-Waterproof-Ventilated-Compartment-Accessories/dp/B09PZZ1QRM" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1408px;"><p class="vanilla-image-block" style="padding-top:106.53%;"><img id="6q42gErTa4JearPAxSRMtk" name="2 Layer Golf Trunk Organizer" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/6q42gErTa4JearPAxSRMtk-1920-80.png" mos="" align="middle" fullscreen="" width="1408" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Organizer-Waterproof-Ventilated-Compartment-Accessories/dp/B09PZZ1QRM" target="_blank" rel="nofollow" data-dimension112="5595de0a-cee7-11f1-a203-cd3ca1ab7d84" data-action="Deal Block" data-label="2 Layer Golf Trunk Organizer" data-dimension48="2 Layer Golf Trunk Organizer" data-dimension25="$32">2 Layer Golf Trunk Organizer: was $35 now $32</a></strong><br />I have this organizer in my trunk, and it's helped me make sure I always have a couple of pairs of golf shoes (I have a couple dozen pairs, so it's good to have some handy) and all my accessories ready to go. Sure, your golfer might just throw the stuff loose in their trunk, but why do that when this organizer is readily available?<a class="view-deal button" href="https://www.amazon.com/Organizer-Waterproof-Ventilated-Compartment-Accessories/dp/B09PZZ1QRM" target="_blank" rel="nofollow" data-dimension112="5595de0a-cee7-11f1-a203-cd3ca1ab7d84" data-action="Deal Block" data-label="2 Layer Golf Trunk Organizer" data-dimension48="2 Layer Golf Trunk Organizer" data-dimension25="$32">View Deal</a></p></div><div class="product"><a data-dimension112="5595de78-cee7-11f1-9b2d-cd38528f2fe5" data-action="Deal Block" data-label="Golf Tumbler 30oz" data-dimension48="Golf Tumbler 30oz" data-dimension25="$39" href="https://www.tallytumbler.com/products/golf-tally-tumbler" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="gB4epwH8ghPQ6HDFKXgF9n" name="Golf Tumbler" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gB4epwH8ghPQ6HDFKXgF9n-1920-80.png" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.tallytumbler.com/products/golf-tally-tumbler" target="_blank" rel="nofollow" data-dimension112="5595de78-cee7-11f1-9b2d-cd38528f2fe5" data-action="Deal Block" data-label="Golf Tumbler 30oz" data-dimension48="Golf Tumbler 30oz" data-dimension25="$39">Golf Tumbler 30oz: $39</a></strong><br />I just tried one of these tumblers, and it's a fun novelty to be sure! Importantly, it also works as a good cup for keeping your liquids cold (or warm) while offering a fun way to track your golf score and stats. If you think the golfer in your life has everything, this might be the perfect gift to get them that they haven't snagged yet. And if you prefer a smaller cup, you can get a <a href="https://www.tallytumbler.com/products/golf-tally-tumbler-20oz" target="_blank" rel="nofollow">20oz version</a>, too.<a class="view-deal button" href="https://www.tallytumbler.com/products/golf-tally-tumbler" target="_blank" rel="nofollow" data-dimension112="5595de78-cee7-11f1-9b2d-cd38528f2fe5" data-action="Deal Block" data-label="Golf Tumbler 30oz" data-dimension48="Golf Tumbler 30oz" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="fc108d08-d4cc-11f1-a997-d3bdd2d1a9e8" data-action="Deal Block" data-label="Advent Calendar" data-dimension48="Advent Calendar" data-dimension25="$89" href="https://www.vicegolf.com/products/vice-advent-calendar-12-days-of-vicemas-24-balls" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2500px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="H9GSGpxBDmrtAncCL58BVo" name="Advent Calendar" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/H9GSGpxBDmrtAncCL58BVo-1920-80.png" mos="" align="middle" fullscreen="" width="2500" height="2500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>This is the perfect gift for the golfer who already has everything. A bunch of fun, limited-edition golf balls in an advent calendar will keep them entertained all holiday season, and they'll end up with two dozen cool golf balls when all is said and done.<a class="view-deal button" href="https://www.vicegolf.com/products/vice-advent-calendar-12-days-of-vicemas-24-balls" target="_blank" rel="nofollow" data-dimension112="fc108d08-d4cc-11f1-a997-d3bdd2d1a9e8" data-action="Deal Block" data-label="Advent Calendar" data-dimension48="Advent Calendar" data-dimension25="$89">View Deal</a></p></div><div class="product"><a data-dimension112="5595dee6-cee7-11f1-b1d4-d39090d8916e" data-action="Deal Block" data-label="Golf Organizer" data-dimension48="Golf Organizer" data-dimension25="$59" href="https://www.amazon.com/Morvat-Organizer-Accessories-Organize-Equipment/dp/B0799QHWF6/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1447px;"><p class="vanilla-image-block" style="padding-top:103.66%;"><img id="tXeeBti6hHdSxbUg9p98Q8" name="91THUOGoGLL._AC_SL1500_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/tXeeBti6hHdSxbUg9p98Q8-1920-80.jpg" mos="" align="middle" fullscreen="" width="1447" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Morvat-Organizer-Accessories-Organize-Equipment/dp/B0799QHWF6/" target="_blank" rel="nofollow" data-dimension112="5595dee6-cee7-11f1-b1d4-d39090d8916e" data-action="Deal Block" data-label="Golf Organizer" data-dimension48="Golf Organizer" data-dimension25="$59">Golf Organizer: $59</a></strong><br />Do you know a golfer with so much equipment that they can't organize it? Then this budget-friendly golf bag organizer is a must. It's designed to hold two bags and has shelves for the rest of the golfer's gear, like their shoes, balls and everything else. Just be sure they have the space for this before buying.<a class="view-deal button" href="https://www.amazon.com/Morvat-Organizer-Accessories-Organize-Equipment/dp/B0799QHWF6/" target="_blank" rel="nofollow" data-dimension112="5595dee6-cee7-11f1-b1d4-d39090d8916e" data-action="Deal Block" data-label="Golf Organizer" data-dimension48="Golf Organizer" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="5595df54-cee7-11f1-893c-5f7074aab882" data-action="Deal Block" data-label="Headcover" data-dimension48="Headcover" data-dimension25="$" href="https://pinsandaces.com/collections/headcovers" 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:125.00%;"><img id="BF97sXJr8AbxQdcmpgt2mg" name="image" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/BF97sXJr8AbxQdcmpgt2mg-1920-80.png" mos="" align="middle" fullscreen="" width="600" height="750" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>Every golfer needs headcovers to protect their woods, hybrids and putter, so getting a stylish, themed one from Pins &amp; Aces is a perfect gift. The company makes some of the most fabulous headcovers on the market, and you can choose from a variety to suit the tastes of the person you're shopping for (there are a ton of options, from licensed brands to original designs).<a class="view-deal button" href="https://pinsandaces.com/collections/headcovers" target="_blank" rel="nofollow" data-dimension112="5595df54-cee7-11f1-893c-5f7074aab882" data-action="Deal Block" data-label="Headcover" data-dimension48="Headcover" data-dimension25="$">View Deal</a></p></div><div class="product"><a data-dimension112="5595dfc2-cee7-11f1-80d2-eb5d0ce750fc" data-action="Deal Block" data-label="Player V Pro" data-dimension48="Player V Pro" data-dimension25="$489" href="https://vesselgolf.com/products/player-v-pro-stand" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1200px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="G2LsbYrPqZmrTngEHUqzub" name="Player V Pro" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/G2LsbYrPqZmrTngEHUqzub-1920-80.png" mos="" align="middle" fullscreen="" width="1200" height="1200" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>To me, Vessel bags epitomize golf luxury. The Player V Pro was the best golf bag I've ever used, but the <a href="https://vesselgolf.com/products/player-vi-pro-stand" target="_blank" rel="nofollow" data-dimension112="5595dfc2-cee7-11f1-80d2-eb5d0ce750fc" data-action="Deal Block" data-label="Player V Pro" data-dimension48="Player V Pro" data-dimension25="$489">Player VI Pro</a> has surpassed it. However, if you want to get a tremendous bag for a little less, I can still easily recommend the Player V Pro! I even had the chance to <a href="https://www.tomsguide.com/wellness/fitness/i-think-we-may-have-the-biggest-market-share-on-tour-vessel-golfs-ceo-and-players-use-the-bags-by-choice">talk to Vessel's CEO</a> about what makes the bags so good.<a class="view-deal button" href="https://vesselgolf.com/products/player-v-pro-stand" target="_blank" rel="nofollow" data-dimension112="5595dfc2-cee7-11f1-80d2-eb5d0ce750fc" data-action="Deal Block" data-label="Player V Pro" data-dimension48="Player V Pro" data-dimension25="$489">View Deal</a></p></div><div class="product"><a data-dimension112="5595e030-cee7-11f1-8311-77ba8d3a8482" data-action="Deal Block" data-label="AI Navigator GPS+ Electric Caddy" data-dimension48="AI Navigator GPS+ Electric Caddy" data-dimension25="$1895" href="https://www.pgatoursuperstore.com/ai-navigator-gps-electric-caddy/2000000043838.html?dwvar_2000000043838_STK_COLOR=5&amp;cgid=golf-bags-carts-ppcart-electric" 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="wuf9d8NExMGrYzZRy4D6H9" name="AI Navigator GPS+ Electric Caddy" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/wuf9d8NExMGrYzZRy4D6H9-1920-80.png" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.pgatoursuperstore.com/ai-navigator-gps-electric-caddy/2000000043838.html?dwvar_2000000043838_STK_COLOR=5&amp;cgid=golf-bags-carts-ppcart-electric" target="_blank" rel="nofollow" data-dimension112="5595e030-cee7-11f1-8311-77ba8d3a8482" data-action="Deal Block" data-label="AI Navigator GPS+ Electric Caddy" data-dimension48="AI Navigator GPS+ Electric Caddy" data-dimension25="$1895">AI Navigator GPS+ Electric Caddy: $1895</a></strong><br />Okay, so this isn't your typical golf gift, as it's super expensive, but if you have a hefty budget and want a gift that most golfers will want but might not want to buy themselves, this is the electric push cart I use to golf every week. Between the rugged, all-terrain design, the GPS screen and all the other well-appointed features, this is the premium gift for any occasion.<a class="view-deal button" href="https://www.pgatoursuperstore.com/ai-navigator-gps-electric-caddy/2000000043838.html?dwvar_2000000043838_STK_COLOR=5&amp;cgid=golf-bags-carts-ppcart-electric" target="_blank" rel="nofollow" data-dimension112="5595e030-cee7-11f1-8311-77ba8d3a8482" data-action="Deal Block" data-label="AI Navigator GPS+ Electric Caddy" data-dimension48="AI Navigator GPS+ Electric Caddy" data-dimension25="$1895">View Deal</a></p></div><h3 class="article-body__section" id="section-golf-gadgets"><span>Golf Gadgets</span></h3><div class="product"><a data-dimension112="5595e116-cee7-11f1-8206-29eedd84ca7d" data-action="Deal Block" data-label="Magnetic Golf Cart Phone Holder" data-dimension48="Magnetic Golf Cart Phone Holder" data-dimension25="$16" href="https://www.amazon.com/Dual-Sided-Magnetic-Holder-Rotatable-Accessories/dp/B0GTLSVQGP" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1300px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="ZzDmKQtMQgWzraDUJzpfY5" name="Magnetic Golf Cart Phone Holder" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZzDmKQtMQgWzraDUJzpfY5-1920-80.png" mos="" align="middle" fullscreen="" width="1300" height="1300" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Dual-Sided-Magnetic-Holder-Rotatable-Accessories/dp/B0GTLSVQGP" target="_blank" rel="nofollow" data-dimension112="5595e116-cee7-11f1-8206-29eedd84ca7d" data-action="Deal Block" data-label="Magnetic Golf Cart Phone Holder" data-dimension48="Magnetic Golf Cart Phone Holder" data-dimension25="$16">Magnetic Golf Cart Phone Holder: was $20 now $16</a></strong><br />This is a cool gift for the golfer who uses their phone as an on-course GPS device (and has a magnetic phone or case). This gives them a great place to put their phone without having to carry it around in their pocket all round.<a class="view-deal button" href="https://www.amazon.com/Dual-Sided-Magnetic-Holder-Rotatable-Accessories/dp/B0GTLSVQGP" target="_blank" rel="nofollow" data-dimension112="5595e116-cee7-11f1-8206-29eedd84ca7d" data-action="Deal Block" data-label="Magnetic Golf Cart Phone Holder" data-dimension48="Magnetic Golf Cart Phone Holder" data-dimension25="$16">View Deal</a></p></div><div class="product"><a data-dimension112="5595e184-cee7-11f1-b20d-c77785fd792f" data-action="Deal Block" data-label="Pop Up Golf Chipping Net" data-dimension48="Pop Up Golf Chipping Net" data-dimension25="$25" href="https://www.amazon.com/Rolilac-Pop-Golf-Chipping-Net/dp/B07GLY5NQQ/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:982px;"><p class="vanilla-image-block" style="padding-top:82.69%;"><img id="FgjnAmmyrjAcvh3oMTGarK" name="71kT3myQjxL._AC_SL1000_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/FgjnAmmyrjAcvh3oMTGarK-1920-80.jpg" mos="" align="middle" fullscreen="" width="982" height="812" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Rolilac-Pop-Golf-Chipping-Net/dp/B07GLY5NQQ/" target="_blank" rel="nofollow" data-dimension112="5595e184-cee7-11f1-b20d-c77785fd792f" data-action="Deal Block" data-label="Pop Up Golf Chipping Net" data-dimension48="Pop Up Golf Chipping Net" data-dimension25="$25">Pop Up Golf Chipping Net: $25</a></strong><br />This portable one is hard to beat for the golfer who would enjoy a simple practice net. It can be used indoors and outdoors to practice chipping, with multiple pockets to hone accuracy and aim. Rounds are won and lost around the greens; this practice tool can make a difference.<a class="view-deal button" href="https://www.amazon.com/Rolilac-Pop-Golf-Chipping-Net/dp/B07GLY5NQQ/" target="_blank" rel="nofollow" data-dimension112="5595e184-cee7-11f1-b20d-c77785fd792f" data-action="Deal Block" data-label="Pop Up Golf Chipping Net" data-dimension48="Pop Up Golf Chipping Net" data-dimension25="$25">View Deal</a></p></div><div class="product"><a data-dimension112="5595e1f2-cee7-11f1-b7f2-15cd8018eb00" data-action="Deal Block" data-label="Golf Swing Trainer Aid" data-dimension48="Golf Swing Trainer Aid" data-dimension25="$40" href="https://www.amazon.com/Amazon-Basics-Golf-Swing-Trainer/dp/B09N3HZK2J" 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:98.87%;"><img id="DTkVcYRPfV6Jt7kQwus6oZ" name="image" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/DTkVcYRPfV6Jt7kQwus6oZ-1920-80.png" mos="" align="middle" fullscreen="" width="1500" height="1483" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Amazon-Basics-Golf-Swing-Trainer/dp/B09N3HZK2J" target="_blank" rel="nofollow" data-dimension112="5595e1f2-cee7-11f1-b7f2-15cd8018eb00" data-action="Deal Block" data-label="Golf Swing Trainer Aid" data-dimension48="Golf Swing Trainer Aid" data-dimension25="$40">Golf Swing Trainer Aid: $40</a></strong><br />Golfers can spend their entire lives mastering their swing, but a trusted accessory for practicing swing sequencing and tempo is a swing trainer like this one. It fits in a golf bag, so golfers can warm up even on the course, as the extra weight helps get the blood flowing, allowing for a looser, more confident swing.<a class="view-deal button" href="https://www.amazon.com/Amazon-Basics-Golf-Swing-Trainer/dp/B09N3HZK2J" target="_blank" rel="nofollow" data-dimension112="5595e1f2-cee7-11f1-b7f2-15cd8018eb00" data-action="Deal Block" data-label="Golf Swing Trainer Aid" data-dimension48="Golf Swing Trainer Aid" data-dimension25="$40">View Deal</a></p></div><div class="product"><a data-dimension112="5595e260-cee7-11f1-b9cd-bb07a5750ff0" data-action="Deal Block" data-label="Putting Mat" data-dimension48="Putting Mat" data-dimension25="$69" href="https://www.amazon.com/CHAMPKEY-Premium-Wooden-Putting-Gates/dp/B0CSPQGX2Y" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1356px;"><p class="vanilla-image-block" style="padding-top:110.62%;"><img id="uUbhMJ8As7f4gCQ6heXuJn" name="81VLGD7Bx0L._AC_SL1500_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/uUbhMJ8As7f4gCQ6heXuJn-1920-80.jpg" mos="" align="middle" fullscreen="" width="1356" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>Yes, golfers <em>do</em> need dedicated training tools for each golf skill. So, if they don't already have a putting mat, this roll-up one would make a great gift. Measuring 10 feet, this training mat can help golfers master their putts, and it even comes with gates to help take the practice up a notch.<a class="view-deal button" href="https://www.amazon.com/CHAMPKEY-Premium-Wooden-Putting-Gates/dp/B0CSPQGX2Y" target="_blank" rel="nofollow" data-dimension112="5595e260-cee7-11f1-b9cd-bb07a5750ff0" data-action="Deal Block" data-label="Putting Mat" data-dimension48="Putting Mat" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="5595e2ce-cee7-11f1-8020-f91e9f108030" data-action="Deal Block" data-label="Complete System" data-dimension48="Complete System" data-dimension25="$175" href="https://pathpalgolf.com/pages/complete-training-package" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1280px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="yB4gvNi4hKZEw5RHeR54f" name="pathpal-white" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/yB4gvNi4hKZEw5RHeR54f-1920-80.jpg" mos="" align="middle" fullscreen="" width="1280" height="1280" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>I've talked before about how much <a href="https://www.tomsguide.com/wellness/fitness/stop-wasting-money-on-a-new-driver-every-year-get-this-simple-training-aid-instead" data-dimension112="5595e2ce-cee7-11f1-8020-f91e9f108030" data-action="Deal Block" data-label="Complete System" data-dimension48="Complete System" data-dimension25="$175">PathPal helped me improve my slice</a>, and I can't recommend this product enough. The complete system comes with all the pieces you need to improve your swing path and get better at golf. Is there a better gift for the golfer in your life than an improved swing? Better swing = more fun. <a class="view-deal button" href="https://pathpalgolf.com/pages/complete-training-package" target="_blank" rel="nofollow" data-dimension112="5595e2ce-cee7-11f1-8020-f91e9f108030" data-action="Deal Block" data-label="Complete System" data-dimension48="Complete System" data-dimension25="$175">View Deal</a></p></div><div class="product"><a data-dimension112="5595e60c-cee7-11f1-9a05-b1da21a2630d" data-action="Deal Block" data-label="Sensor 4" data-dimension48="Sensor 4" data-dimension25="$345" href="https://hackmotion.com/hackmotion-sensor-4/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:200px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="LMgvQfbLfbhtcrDihEYTnE" name="image" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/LMgvQfbLfbhtcrDihEYTnE-1920-80.png" mos="" align="middle" fullscreen="" width="200" height="200" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://hackmotion.com/hackmotion-sensor-4/" target="_blank" rel="nofollow" data-dimension112="5595e60c-cee7-11f1-9a05-b1da21a2630d" data-action="Deal Block" data-label="Sensor 4" data-dimension48="Sensor 4" data-dimension25="$345">Sensor 4: $345</a></strong><br />I've spent the last few months practicing with HackMotion's wrist-based training tool, the <a href="https://hackmotion.com/hackmotion-sensor-3/" target="_blank" rel="nofollow">Sensor 3</a>, and I'm constantly blown away by how much you can learn about your golf swing just from your wrist angles. I've noticeably improved both my ball striking and tee shots since using this fancy golf tech, and I can't imagine practicing without it.<a class="view-deal button" href="https://hackmotion.com/hackmotion-sensor-4/" target="_blank" rel="nofollow" data-dimension112="5595e60c-cee7-11f1-9a05-b1da21a2630d" data-action="Deal Block" data-label="Sensor 4" data-dimension48="Sensor 4" data-dimension25="$345">View Deal</a></p></div><div class="product"><a data-dimension112="5595e698-cee7-11f1-938a-0577624049ba" data-action="Deal Block" data-label="Air" data-dimension48="Air" data-dimension25="$349" href="https://www.arccosgolf.com/pages/us-air-sl" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="B6KJ7gsv8Nqxiqc8QhfmdY" name="Air" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/B6KJ7gsv8Nqxiqc8QhfmdY-1920-80.png" mos="" align="middle" fullscreen="" width="1800" height="1800" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>For my money, no product on the golf market beats Arccos. Since I started golfing, I've tracked my game with the <a href="https://www.arccosgolf.com/products/smart-sensors" target="_blank" data-dimension112="5595e698-cee7-11f1-938a-0577624049ba" data-action="Deal Block" data-label="Air" data-dimension48="Air" data-dimension25="$349">club sensors</a>, and now the company offers the Air, which provides the same level of tracking without anything on the clubs. If the golfer you love is looking to improve their game, this is the gift to buy.<a class="view-deal button" href="https://www.arccosgolf.com/pages/us-air-sl" target="_blank" rel="nofollow" data-dimension112="5595e698-cee7-11f1-938a-0577624049ba" data-action="Deal Block" data-label="Air" data-dimension48="Air" data-dimension25="$349">View Deal</a></p></div><div class="product"><a data-dimension112="5595e706-cee7-11f1-995c-6b980055cb29" data-action="Deal Block" data-label="Approach R10" data-dimension48="Approach R10" data-dimension25="$499" href="https://www.amazon.com/Garmin-Approach-Portable-Monitor-Indoors/dp/B095QX1FSR" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1470px;"><p class="vanilla-image-block" style="padding-top:102.04%;"><img id="PkuskGztGMrF4kpQkN95nF" name="61POLvv99xS._AC_SL1500_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/PkuskGztGMrF4kpQkN95nF-1920-80.jpg" mos="" align="middle" fullscreen="" width="1470" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The <a href="https://www.tomsguide.com/Garmin-approach-R10-review" data-dimension112="5595e706-cee7-11f1-995c-6b980055cb29" data-action="Deal Block" data-label="Approach R10" data-dimension48="Approach R10" data-dimension25="$499">Garmin Approach R10</a> golf launch monitor is a tremendous big-ticket gift for the golfer looking to measure their game. This clever gadget analyzes swings and shots to offer guidance in a companion app, and it even works as a complete golf simulator. Compared with others on the market, it's very reasonably priced, making it a good gift.<a class="view-deal button" href="https://www.amazon.com/Garmin-Approach-Portable-Monitor-Indoors/dp/B095QX1FSR" target="_blank" rel="nofollow" data-dimension112="5595e706-cee7-11f1-995c-6b980055cb29" data-action="Deal Block" data-label="Approach R10" data-dimension48="Approach R10" data-dimension25="$499">View Deal</a></p></div><div class="product"><a data-dimension112="805b5466-d38e-11f1-be8f-d91764ba5f0a" data-action="Deal Block" data-label="Approach S72" data-dimension48="Approach S72" data-dimension25="$799" href="https://www.garmin.com/en-US/p/1937140/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1490px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="EE5wYJphQpkqPstx5iSizN" name="Approach S72" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/EE5wYJphQpkqPstx5iSizN-1920-80.png" mos="" align="middle" fullscreen="" width="1490" height="1490" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.garmin.com/en-US/p/1937140/" target="_blank" rel="nofollow" data-dimension112="805b5466-d38e-11f1-be8f-d91764ba5f0a" data-action="Deal Block" data-label="Approach S72" data-dimension48="Approach S72" data-dimension25="$799">Approach S72: $799</a></strong><br />This Garmin smartwatch has more features than any other golf watch on the market, and it's no contest. I started using it, and I'm blown away. It has wrist sensing, which is perfect for the driving range. It also helps with green reading, lets you see how your heart rate affects your golf performance and offers maps, scoring and more. It's expensive, but for the features, it doesn't feel overpriced. <a class="view-deal button" href="https://www.garmin.com/en-US/p/1937140/" target="_blank" rel="nofollow" data-dimension112="805b5466-d38e-11f1-be8f-d91764ba5f0a" data-action="Deal Block" data-label="Approach S72" data-dimension48="Approach S72" data-dimension25="$799">View Deal</a></p></div><h3 class="article-body__section" id="section-off-course-golf-gifts"><span>Off-Course Golf Gifts</span></h3><div class="product"><a data-dimension112="5595e7d8-cee7-11f1-93aa-27a04ca61e8b" data-action="Deal Block" data-label="Golfer's Scratch Off Poster" data-dimension48="Golfer's Scratch Off Poster" data-dimension25="$25" href="https://www.uncommongoods.com/product/golfers-scratch-off-poster" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="xxLsMrXyZxsrKd5M7Hei4F" name="courses.png" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/xxLsMrXyZxsrKd5M7Hei4F-1920-80.png" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.uncommongoods.com/product/golfers-scratch-off-poster" target="_blank" rel="nofollow" data-dimension112="5595e7d8-cee7-11f1-93aa-27a04ca61e8b" data-action="Deal Block" data-label="Golfer's Scratch Off Poster" data-dimension48="Golfer's Scratch Off Poster" data-dimension25="$25">Golfer's Scratch Off Poster: $25</a></strong><br />If you know a golfer who travels to play famous courses, this scratch-off poster from Uncommon Goods is a thoughtful gift idea. This way, they can keep track of where they've played and where they should book a trip to next.<a class="view-deal button" href="https://www.uncommongoods.com/product/golfers-scratch-off-poster" target="_blank" rel="nofollow" data-dimension112="5595e7d8-cee7-11f1-93aa-27a04ca61e8b" data-action="Deal Block" data-label="Golfer's Scratch Off Poster" data-dimension48="Golfer's Scratch Off Poster" data-dimension25="$25">View Deal</a></p></div><div class="product"><a data-dimension112="5595e83c-cee7-11f1-bf96-b9633b57e35f" data-action="Deal Block" data-label="Nextgen Den Caddy" data-dimension48="Nextgen Den Caddy" data-dimension25="$105" href="https://www.pxg.com/products/nextgen-den-caddy" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1440px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="RuCWdBXEop2ZpzQAKN44XX" name="Nextgen Den Caddy" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/RuCWdBXEop2ZpzQAKN44XX-1920-80.png" mos="" align="middle" fullscreen="" width="1440" height="1440" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.pxg.com/products/nextgen-den-caddy" target="_blank" rel="nofollow" data-dimension112="5595e83c-cee7-11f1-bf96-b9633b57e35f" data-action="Deal Block" data-label="Nextgen Den Caddy" data-dimension48="Nextgen Den Caddy" data-dimension25="$105">Nextgen Den Caddy: $105</a></strong><br />A den caddy is a fun thing to have around the house for storing clubs, balls or just about anything else. It's like a mini golf bag that happens to look cool. I have a PXG den caddy in my simulator for storing my various training aids (some of which are outlined above), but it's just a cool accessory to have around, and at $105, PXG's is one of the more reasonably priced options.<a class="view-deal button" href="https://www.pxg.com/products/nextgen-den-caddy" target="_blank" rel="nofollow" data-dimension112="5595e83c-cee7-11f1-bf96-b9633b57e35f" data-action="Deal Block" data-label="Nextgen Den Caddy" data-dimension48="Nextgen Den Caddy" data-dimension25="$105">View Deal</a></p></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Skechers walking shoes are up to 61% off — 21 best deals on sneakers, slip-ins and fall boots ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Black Friday excitement is building! If you just can't wait, there's no need to worry — <a href="https://www.amazon.com/stores/page/37AAEB46-A955-4D92-957D-28A4B4B3FDE2" target="_blank" rel="nofollow">Amazon is offering huge price drops on Skechers</a> right now. Whether you're on the hunt for sneakers or cozy fall boots, I'm sharing all the best styles.</p><p>The shoe I'm most interested in right now is the <a href="https://www.amazon.com/Skechers-Sport-Womens-Slip-INS-Sneaker/dp/B0F3RMY5YF" target="_blank" rel="nofollow">Skechers Contour Foam Cozy Fit on sale from $50</a>. Not only are they the perfect comfy fall sneakers, they have one of the best color selections of any pair of Skechers you can buy right now.</p><p><strong>Note: </strong>Prices vary depending on the size and color you choose. Check out any different color options available in your size to find the best deals. For more, check out our <a href="https://www.tomsguide.com/coupons/amazon.com">Amazon promo codes</a>.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><strong></strong><a href="https://www.amazon.com/stores/page/37AAEB46-A955-4D92-957D-28A4B4B3FDE2" target="_blank" rel="nofollow"><strong>shop all Skechers deals at Amazon</strong></a></li><li><strong>Virtue Stunner (Women's): </strong><a href="https://www.amazon.com/Skechers-Womens-Sport-Active-Virtue/dp/B0FNCB7C3X/" target="_blank" rel="nofollow"><strong>was $58 now from $25</strong></a></li><li><strong>Go Walk Arch Fit N-Joy Nate (Men's): </strong><a href="https://www.amazon.com/Skechers-Mens-N-Joy-Sneaker-White/dp/B0FDMS3F5K" target="_blank" rel="nofollow"><strong>was $78 now from $38</strong></a></li><li><strong>Keepsakes Cozy - Cozy Cascade (Women's): </strong><a href="https://www.amazon.com/Skechers-Womens-KEEPSAKES-COZY-Chestnut/dp/B0GPD3LSTC" target="_blank" rel="nofollow"><strong>was $55 now from $41</strong></a></li><li><strong>Summits Louvin Slip-Ins (Men's): </strong><a href="https://www.amazon.com/Skechers-Summits-Louvin-Loafer-Black/dp/B0864TFM51" target="_blank" rel="nofollow"><strong>was $70 now from $45</strong></a></li><li><strong>Summits Key Pace Slip-ins (Men's): </strong><a href="https://www.amazon.com/Skechers-Summits-Hands-Slip-Loafer/dp/B0H2K13WJL" target="_blank" rel="nofollow"><strong>was $72 now from $56</strong></a></li><li><strong>Refine 2.0 Nora (Women's): </strong><a href="https://www.amazon.com/Skechers-Womens-Sport-Active-Refine/dp/B0G1PK31X7" target="_blank" rel="nofollow"><strong>was $84 now from $57</strong></a></li><li><strong>Segment Rilar (Men's): </strong><a href="https://www.amazon.com/Skechers-Segment-Rilar-Oxford-Brown/dp/B00I1JPY76" target="_blank" rel="nofollow"><strong>was $95 now from $59</strong></a></li><li><strong>Go Walk Max Cushioning Hyper Burst Zoltar (Men's): </strong><a href="https://www.amazon.com/Skechers-Cushioning-Slip-Ins-Sneaker-Charcoal/dp/B0GY6FY26K" target="_blank" rel="nofollow"><strong>was $94 now from $81</strong></a></li><li><strong>Aero Razor Running Shoes (Women's): </strong><a href="https://www.amazon.com/Skechers-Womens-Razor-Turquoise-Medium/dp/B0GVPVGG8C" target="_blank" rel="nofollow"><strong>was $140 now from $91</strong></a></li></ul><h3 class="article-body__section" id="section-skechers-deals-women-s"><span>Skechers deals (Women's)</span></h3><div class="product"><a data-dimension112="c1b22920-cecb-11f1-9f29-c55ce8bef84a" data-action="Deal Block" data-label="Virtue Stunner (Women's)" data-dimension48="Virtue Stunner (Women's)" data-dimension25="$25" href="https://www.amazon.com/Skechers-Womens-Sport-Active-Virtue/dp/B0FNC7ZZD1/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:64.32%;"><img id="fuQGoHerZPQAPL7bem8Pic" name="Virtue Stunner (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/fuQGoHerZPQAPL7bem8Pic-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="447" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Sport-Active-Virtue/dp/B0FNC7ZZD1/" target="_blank" rel="nofollow" data-dimension112="c1b22920-cecb-11f1-9f29-c55ce8bef84a" data-action="Deal Block" data-label="Virtue Stunner (Women's)" data-dimension48="Virtue Stunner (Women's)" data-dimension25="$25">Virtue Stunner (Women's): was $59 now $25</a></strong><br />This is another hefty Skechers discount that you'll have to act fast to grab, if they're available in your size. Currently on 57% off in Grey and 50% off in Natural, these super-simple, super-comfortable shoes have a soft knit upper and air-cooled memory foam insoles.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Sport-Active-Virtue/dp/B0FNC7ZZD1/" target="_blank" rel="nofollow" data-dimension112="c1b22920-cecb-11f1-9f29-c55ce8bef84a" data-action="Deal Block" data-label="Virtue Stunner (Women's)" data-dimension48="Virtue Stunner (Women's)" data-dimension25="$25">View Deal</a></p></div><div class="product"><a data-dimension112="913130c8-cec8-11f1-922c-ad116ac9d3cd" data-action="Deal Block" data-label="Refine 2.0 Nora (Women's)" data-dimension48="Refine 2.0 Nora (Women's)" data-dimension25="$35" href="https://www.amazon.com/Skechers-Womens-Sport-Active-Refine/dp/B0G1P5DSL6" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:66.91%;"><img id="XtYccaXnTY5XF946soUYSE" name="Refine 2.0 Nora (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XtYccaXnTY5XF946soUYSE-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="465" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Sport-Active-Refine/dp/B0G1P5DSL6" target="_blank" rel="nofollow" data-dimension112="913130c8-cec8-11f1-922c-ad116ac9d3cd" data-action="Deal Block" data-label="Refine 2.0 Nora (Women's)" data-dimension48="Refine 2.0 Nora (Women's)" data-dimension25="$35">Refine 2.0 Nora (Women's): was $84 now $35</a></strong><br />These Skechers have seen an impressive 58% discount when you check to apply the coupon on Amazon's page. Incredibly easy to wear, they feature a stretch knit upper, arch-fit insoles and are machine washable. <a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Sport-Active-Refine/dp/B0G1P5DSL6" target="_blank" rel="nofollow" data-dimension112="913130c8-cec8-11f1-922c-ad116ac9d3cd" data-action="Deal Block" data-label="Refine 2.0 Nora (Women's)" data-dimension48="Refine 2.0 Nora (Women's)" data-dimension25="$35">View Deal</a></p></div><div class="product"><a data-dimension112="91313136-cec8-11f1-8ab9-7b04dd6482f5" data-action="Deal Block" data-label="Bobs Keepsakes Lite Slipper (Women's)" data-dimension48="Bobs Keepsakes Lite Slipper (Women's)" data-dimension25="$39" href="https://www.amazon.com/Skechers-Keepsakes-Lite-Cozy-Slipper-Chestnut/dp/B0BX22T5PF/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1181px;"><p class="vanilla-image-block" style="padding-top:58.85%;"><img id="ut3KQ3LGhZKe4rhieo9nsK" name="719iDVut31L._AC_SY695" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ut3KQ3LGhZKe4rhieo9nsK-1920-80.png" mos="" align="middle" fullscreen="" width="1181" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Keepsakes-Lite-Cozy-Slipper-Chestnut/dp/B0BX22T5PF/" target="_blank" rel="nofollow" data-dimension112="91313136-cec8-11f1-8ab9-7b04dd6482f5" data-action="Deal Block" data-label="Bobs Keepsakes Lite Slipper (Women's)" data-dimension48="Bobs Keepsakes Lite Slipper (Women's)" data-dimension25="$39">Bobs Keepsakes Lite Slipper (Women's): was $51 now $39</a></strong><br />Get yourself prepared for winter extra early with these cozy, lined Skechers slippers. With memory-foam insoles, faux fur trim and traction outer sole, these snug slippers will keep you warm, no matter where you wear them.  <a class="view-deal button" href="https://www.amazon.com/Skechers-Keepsakes-Lite-Cozy-Slipper-Chestnut/dp/B0BX22T5PF/" target="_blank" rel="nofollow" data-dimension112="91313136-cec8-11f1-8ab9-7b04dd6482f5" data-action="Deal Block" data-label="Bobs Keepsakes Lite Slipper (Women's)" data-dimension48="Bobs Keepsakes Lite Slipper (Women's)" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="c1b229ac-cecb-11f1-a96f-d55b9dd5dd35" data-action="Deal Block" data-label="Keepsakes Cozy - Cozy Cascade (Women's)" data-dimension48="Keepsakes Cozy - Cozy Cascade (Women's)" data-dimension25="$41" href="https://www.amazon.com/Skechers-Womens-KEEPSAKES-COZY-Chestnut/dp/B0GPMGKPT8" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:55.68%;"><img id="hYSZfU9nU4nzZJ6fSLnpeZ" name="Keepsakes Cozy - Cozy Cascade (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hYSZfU9nU4nzZJ6fSLnpeZ-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="387" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-KEEPSAKES-COZY-Chestnut/dp/B0GPMGKPT8" target="_blank" rel="nofollow" data-dimension112="c1b229ac-cecb-11f1-a96f-d55b9dd5dd35" data-action="Deal Block" data-label="Keepsakes Cozy - Cozy Cascade (Women's)" data-dimension48="Keepsakes Cozy - Cozy Cascade (Women's)" data-dimension25="$41">Keepsakes Cozy - Cozy Cascade (Women's): was $55 now $41</a></strong><br />You can't have enough cozy pairs of slippers, especially this time of year. These Skechers stand out for their pretty embroidered design on the cuff, and have a soft fuzzy lining — plus Skechers memory foam.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-KEEPSAKES-COZY-Chestnut/dp/B0GPMGKPT8" target="_blank" rel="nofollow" data-dimension112="c1b229ac-cecb-11f1-a96f-d55b9dd5dd35" data-action="Deal Block" data-label="Keepsakes Cozy - Cozy Cascade (Women's)" data-dimension48="Keepsakes Cozy - Cozy Cascade (Women's)" data-dimension25="$41">View Deal</a></p></div><div class="product"><a data-dimension112="91313352-cec8-11f1-b43d-51f87ac772f8" data-action="Deal Block" data-label="Contour Foam Cozy Fit Slip-Ins (Women's)" data-dimension48="Contour Foam Cozy Fit Slip-Ins (Women's)" data-dimension25="$50" href="https://www.amazon.com/Skechers-Sport-Womens-Slip-INS-Sneaker/dp/B0F3RMY5YF" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:66.91%;"><img id="Upd6k99BCo75ngNtEoAdxJ" name="Contour Foam Cozy Fit Slip-Ins (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Upd6k99BCo75ngNtEoAdxJ-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="465" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Sport-Womens-Slip-INS-Sneaker/dp/B0F3RMY5YF" target="_blank" rel="nofollow" data-dimension112="91313352-cec8-11f1-b43d-51f87ac772f8" data-action="Deal Block" data-label="Contour Foam Cozy Fit Slip-Ins (Women's)" data-dimension48="Contour Foam Cozy Fit Slip-Ins (Women's)" data-dimension25="$50">Contour Foam Cozy Fit Slip-Ins (Women's): was $89 now $50</a></strong><br />I love the look of these Skechers, because of the two-tone design — you can get them in white paired with a bunch of other accent colors. As well as looking great, they have a Contour Foam midsole that adapts to your foot's shape, making them some of the comfiest-feeling shoes around.<a class="view-deal button" href="https://www.amazon.com/Skechers-Sport-Womens-Slip-INS-Sneaker/dp/B0F3RMY5YF" target="_blank" rel="nofollow" data-dimension112="91313352-cec8-11f1-b43d-51f87ac772f8" data-action="Deal Block" data-label="Contour Foam Cozy Fit Slip-Ins (Women's)" data-dimension48="Contour Foam Cozy Fit Slip-Ins (Women's)" data-dimension25="$50">View Deal</a></p></div><div class="product"><a data-dimension112="c1b22a24-cecb-11f1-818f-fffaa8c68890" data-action="Deal Block" data-label="Keepsakes Cozy Cozy Mini Slip-Ins Boot (Women's)" data-dimension48="Keepsakes Cozy Cozy Mini Slip-Ins Boot (Women's)" data-dimension25="$52" href="https://www.amazon.com/Skechers-Womens-KEEPSAKES-COZY-Slip-Ins/dp/B0GZJHW6DJ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:72.23%;"><img id="C6vf8hr9LiPZZL7EueMWZH" name="Keepsakes Cozy Cozy Mini Slip-Ins Boot (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/C6vf8hr9LiPZZL7EueMWZH-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="502" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-KEEPSAKES-COZY-Slip-Ins/dp/B0GZJHW6DJ" target="_blank" rel="nofollow" data-dimension112="c1b22a24-cecb-11f1-818f-fffaa8c68890" data-action="Deal Block" data-label="Keepsakes Cozy Cozy Mini Slip-Ins Boot (Women's)" data-dimension48="Keepsakes Cozy Cozy Mini Slip-Ins Boot (Women's)" data-dimension25="$52">Keepsakes Cozy Cozy Mini Slip-Ins Boot (Women's): was $75 now $52</a></strong><br />Double the cozy! Skechers seems to have taken some style cues from Ugg here with a slip-in, wool-lined boot. The heart-shaped charm on the side is a nice touch.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-KEEPSAKES-COZY-Slip-Ins/dp/B0GZJHW6DJ" target="_blank" rel="nofollow" data-dimension112="c1b22a24-cecb-11f1-818f-fffaa8c68890" data-action="Deal Block" data-label="Keepsakes Cozy Cozy Mini Slip-Ins Boot (Women's)" data-dimension48="Keepsakes Cozy Cozy Mini Slip-Ins Boot (Women's)" data-dimension25="$52">View Deal</a></p></div><div class="product"><a data-dimension112="91313488-cec8-11f1-969e-15c257f47827" data-action="Deal Block" data-label="Uno - Champagne &amp; Roses (Women's)" data-dimension48="Uno - Champagne &amp; Roses (Women's)" data-dimension25="$53" href="https://www.amazon.com/Skechers-Street-Womens-UNO-Champagne/dp/B0FN6Y36CP" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:73.09%;"><img id="k9WB77eyZDmMW3XwNPTVym" name="Uno - Champagne &amp; Roses (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/k9WB77eyZDmMW3XwNPTVym-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="508" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Street-Womens-UNO-Champagne/dp/B0FN6Y36CP" target="_blank" rel="nofollow" data-dimension112="91313488-cec8-11f1-969e-15c257f47827" data-action="Deal Block" data-label="Uno - Champagne &amp; Roses (Women's)" data-dimension48="Uno - Champagne &amp; Roses (Women's)" data-dimension25="$53">Uno - Champagne &amp; Roses (Women's): was $83 now $53</a></strong><br />Need a practical gift? These shoes are perfect for the job since they look super stylish and are extremely comfortable. The rose petal decor further elevates the look.<a class="view-deal button" href="https://www.amazon.com/Skechers-Street-Womens-UNO-Champagne/dp/B0FN6Y36CP" target="_blank" rel="nofollow" data-dimension112="91313488-cec8-11f1-969e-15c257f47827" data-action="Deal Block" data-label="Uno - Champagne &amp; Roses (Women's)" data-dimension48="Uno - Champagne &amp; Roses (Women's)" data-dimension25="$53">View Deal</a></p></div><div class="product"><a data-dimension112="c1b22a9c-cecb-11f1-a4d1-d3fbd5fd194c" data-action="Deal Block" data-label="Glide-Step Pro Soft Mirage (Women's)" data-dimension48="Glide-Step Pro Soft Mirage (Women's)" data-dimension25="$61" href="https://www.amazon.com/Skechers-Womens-Glide-Step-Soft-Mirage/dp/B0HMJWHM8D" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:70.36%;"><img id="gENhFcxWPfR5eGzmaeeMrZ" name="Glide-Step Pro Soft Mirage (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gENhFcxWPfR5eGzmaeeMrZ-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="489" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Glide-Step-Soft-Mirage/dp/B0HMJWHM8D" target="_blank" rel="nofollow" data-dimension112="c1b22a9c-cecb-11f1-a4d1-d3fbd5fd194c" data-action="Deal Block" data-label="Glide-Step Pro Soft Mirage (Women's)" data-dimension48="Glide-Step Pro Soft Mirage (Women's)" data-dimension25="$61">Glide-Step Pro Soft Mirage (Women's): was $78 now $61</a></strong><br />The Skechers Glide-Step offer improved movement and momentum, making every step feel lighter and more energetic. These Soft Mirage sneakers deliver all that as well as a sleek, understated style.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Glide-Step-Soft-Mirage/dp/B0HMJWHM8D" target="_blank" rel="nofollow" data-dimension112="c1b22a9c-cecb-11f1-a4d1-d3fbd5fd194c" data-action="Deal Block" data-label="Glide-Step Pro Soft Mirage (Women's)" data-dimension48="Glide-Step Pro Soft Mirage (Women's)" data-dimension25="$61">View Deal</a></p></div><div class="product star-deal"><a data-dimension112="91313424-cec8-11f1-b781-a32374e2b11a" data-action="Star Deal Block" data-label="Go Run Elevate 2.0 Sneaker (Women's)" data-dimension48="Go Run Elevate 2.0 Sneaker (Women's)" data-dimension25="$64" href="https://www.amazon.com/Skechers-Womens-Elevate-Sneaker-Black/dp/B0CNP8Z6FM" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:52.81%;"><img id="vCHwenty55qSsiSaaAhmLh" name="Go Run Elevate 2.0 Sneaker (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vCHwenty55qSsiSaaAhmLh-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="367" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Elevate-Sneaker-Black/dp/B0CNP8Z6FM" target="_blank" rel="nofollow" data-dimension112="91313424-cec8-11f1-b781-a32374e2b11a" data-action="Star Deal Block" data-label="Go Run Elevate 2.0 Sneaker (Women's)" data-dimension48="Go Run Elevate 2.0 Sneaker (Women's)" data-dimension25="$64">Go Run Elevate 2.0 Sneaker (Women's): was $85 now $64</a></strong><br />If you're hitting the road, these Skechers are an excellent choice. Our <a href="https://www.tomsguide.com/wellness/running/skechers-go-run-elevate-2-review">Skechers Go Run Elevate 2.0 review</a> said that these are great for beginner runners thanks to their affordable price point, bouncy and propulsive soles and breathable design. These sneakers were originally priced at $85, but now you can get them for $64.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Elevate-Sneaker-Black/dp/B0CNP8Z6FM" target="_blank" rel="nofollow" data-dimension112="91313424-cec8-11f1-b781-a32374e2b11a" data-action="Star Deal Block" data-label="Go Run Elevate 2.0 Sneaker (Women's)" data-dimension48="Go Run Elevate 2.0 Sneaker (Women's)" data-dimension25="$64">View Deal</a></p></div><div class="product"><a data-dimension112="c1b22b00-cecb-11f1-9b5f-dbddd6d2807b" data-action="Deal Block" data-label="Easy Going - Warm Occasion - Hands Free Slip-ins (Women's)" data-dimension48="Easy Going - Warm Occasion - Hands Free Slip-ins (Women's)" data-dimension25="$80" href="https://www.amazon.com/Skechers-Womens-EASY-GOING-Chocolate/dp/B0GPD6P9F9" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:77.99%;"><img id="6SS6HJuer92iBVzNnRbUbU" name="Easy Going - Warm Occasion - Hands Free Slip-ins (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/6SS6HJuer92iBVzNnRbUbU-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="542" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-EASY-GOING-Chocolate/dp/B0GPD6P9F9" target="_blank" rel="nofollow" data-dimension112="c1b22b00-cecb-11f1-9b5f-dbddd6d2807b" data-action="Deal Block" data-label="Easy Going - Warm Occasion - Hands Free Slip-ins (Women's)" data-dimension48="Easy Going - Warm Occasion - Hands Free Slip-ins (Women's)" data-dimension25="$80">Easy Going - Warm Occasion - Hands Free Slip-ins (Women's): was $95 now $80</a></strong><br />These cozy Skechers boots are basically an essential this season. They slip on easily and bring both cushioning and warmth that you won't want to go without on your fall walks.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-EASY-GOING-Chocolate/dp/B0GPD6P9F9" target="_blank" rel="nofollow" data-dimension112="c1b22b00-cecb-11f1-9b5f-dbddd6d2807b" data-action="Deal Block" data-label="Easy Going - Warm Occasion - Hands Free Slip-ins (Women's)" data-dimension48="Easy Going - Warm Occasion - Hands Free Slip-ins (Women's)" data-dimension25="$80">View Deal</a></p></div><div class="product"><a data-dimension112="913134f6-cec8-11f1-8420-c503bd559b16" data-action="Deal Block" data-label="Max Cushioning Elite 2.0 (Women's)" data-dimension48="Max Cushioning Elite 2.0 (Women's)" data-dimension25="$84" href="https://www.amazon.com/Skechers-Cushioning-Elite-Natural-Pink/dp/B0BZ93LKDQ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:63.60%;"><img id="DDNtxm7NqaHbqokBvRhcxe" name="Skechers Max Cushioning Elite 2.0" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/DDNtxm7NqaHbqokBvRhcxe-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="442" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Cushioning-Elite-Natural-Pink/dp/B0BZ93LKDQ" target="_blank" rel="nofollow" data-dimension112="913134f6-cec8-11f1-8420-c503bd559b16" data-action="Deal Block" data-label="Max Cushioning Elite 2.0 (Women's)" data-dimension48="Max Cushioning Elite 2.0 (Women's)" data-dimension25="$84">Max Cushioning Elite 2.0 (Women's): was $100 now $84</a></strong><br />These are a pair of comfortable, max-cushioned shoes, best suited to easy miles and long runs. They are hailed as cheaper dupes for the <a href="https://www.tomsguide.com/reviews/hoka-clifton-9">Hoka Clifton 9</a> trainers, without the price tag. Best suited to beginners, or runners looking for a plush shoe to wear for easy miles and long walks, these are a decent option. Read our <a href="https://www.tomsguide.com/wellness/fitness/skechers-max-cushioning-elite-2-0-review">Skechers Max Cushioning Elite 2.0 review</a> for all the info.<a class="view-deal button" href="https://www.amazon.com/Skechers-Cushioning-Elite-Natural-Pink/dp/B0BZ93LKDQ" target="_blank" rel="nofollow" data-dimension112="913134f6-cec8-11f1-8420-c503bd559b16" data-action="Deal Block" data-label="Max Cushioning Elite 2.0 (Women's)" data-dimension48="Max Cushioning Elite 2.0 (Women's)" data-dimension25="$84">View Deal</a></p></div><div class="product"><a data-dimension112="9131362c-cec8-11f1-8251-7fa7af1c2d72" data-action="Deal Block" data-label="Max Cushioning Endeavour Pace Rhythm (Women's)" data-dimension48="Max Cushioning Endeavour Pace Rhythm (Women's)" data-dimension25="$85" href="https://www.amazon.com/Skechers-Womens-Slip-Ins-Cushioning-Endeavour/dp/B0GY6J4H4G" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:59.57%;"><img id="gX8x3dDgKEF8A5TFTT62gg" name="Max Cushioning Endeavour Pace Rhythm (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gX8x3dDgKEF8A5TFTT62gg-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="414" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Slip-Ins-Cushioning-Endeavour/dp/B0GY6J4H4G" target="_blank" rel="nofollow" data-dimension112="9131362c-cec8-11f1-8251-7fa7af1c2d72" data-action="Deal Block" data-label="Max Cushioning Endeavour Pace Rhythm (Women's)" data-dimension48="Max Cushioning Endeavour Pace Rhythm (Women's)" data-dimension25="$85">Max Cushioning Endeavour Pace Rhythm (Women's): was $105 now $85</a></strong><br />Though they're on the expensive side of Skechers' offerings, these running shoes make a statement and offer tons of comfortable cushioning. The Goga Mat insole propels you forwards and the rocker shape helps your steps transition naturally.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Slip-Ins-Cushioning-Endeavour/dp/B0GY6J4H4G" target="_blank" rel="nofollow" data-dimension112="9131362c-cec8-11f1-8251-7fa7af1c2d72" data-action="Deal Block" data-label="Max Cushioning Endeavour Pace Rhythm (Women's)" data-dimension48="Max Cushioning Endeavour Pace Rhythm (Women's)" data-dimension25="$85">View Deal</a></p></div><div class="product"><a data-dimension112="913135be-cec8-11f1-af62-7fe0a945fa4b" data-action="Deal Block" data-label="Aero Razor Running Shoes (Women's)" data-dimension48="Aero Razor Running Shoes (Women's)" data-dimension25="$91" href="https://www.amazon.com/Skechers-Womens-Razor-Turquoise-Medium/dp/B0GVPVGG8C" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:56.69%;"><img id="aqUWsueeM3Z3zz4bY64ro4" name="Aero Razor Running Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/aqUWsueeM3Z3zz4bY64ro4-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="394" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Razor-Turquoise-Medium/dp/B0GVPVGG8C" target="_blank" rel="nofollow" data-dimension112="913135be-cec8-11f1-af62-7fe0a945fa4b" data-action="Deal Block" data-label="Aero Razor Running Shoes (Women's)" data-dimension48="Aero Razor Running Shoes (Women's)" data-dimension25="$91">Aero Razor Running Shoes (Women's): was $140 now $91</a></strong><br />We loved these shoes in our <a href="https://www.tomsguide.com/wellness/running/skechers-aero-razor-review">Skechers Aero Razor review</a>! Our testers said this is a great pair of lightweight shoes for runners who want to pick up speed. You'll find more cushioning elsewhere, but these running shoes bring a super energetic feel to every step you take.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Razor-Turquoise-Medium/dp/B0GVPVGG8C" target="_blank" rel="nofollow" data-dimension112="913135be-cec8-11f1-af62-7fe0a945fa4b" data-action="Deal Block" data-label="Aero Razor Running Shoes (Women's)" data-dimension48="Aero Razor Running Shoes (Women's)" data-dimension25="$91">View Deal</a></p></div><div class="product"><a data-dimension112="9131369a-cec8-11f1-b1eb-93110f318f78" data-action="Deal Block" data-label="Go Walk Workout Walker (Women's)" data-dimension48="Go Walk Workout Walker (Women's)" data-dimension25="$117" href="https://www.amazon.com/Skechers-Womens-Slip-Ins-Workout-Walker/dp/B0GTRTRK9P" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:59.42%;"><img id="g6Fbk2tgHp3unLKa8Gkd3g" name="Go Walk Workout Walker (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/g6Fbk2tgHp3unLKa8Gkd3g-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="413" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Slip-Ins-Workout-Walker/dp/B0GTRTRK9P" target="_blank" rel="nofollow" data-dimension112="9131369a-cec8-11f1-b1eb-93110f318f78" data-action="Deal Block" data-label="Go Walk Workout Walker (Women's)" data-dimension48="Go Walk Workout Walker (Women's)" data-dimension25="$117">Go Walk Workout Walker (Women's): was $135 now $117</a></strong><br />One of the <a href="https://www.tomsguide.com/best-picks/best-skechers-shoes-in-year">best Skechers</a> we've tested, the <a href="https://www.tomsguide.com/reviews/skechers-go-walk-workout-walker">Skechers Go Walk Workout Walker</a>, has gotten a new look. I love the new color options — plus you get a slip-in fit, super-soft cushioning and air cooled memory foam on board.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Slip-Ins-Workout-Walker/dp/B0GTRTRK9P" target="_blank" rel="nofollow" data-dimension112="9131369a-cec8-11f1-b1eb-93110f318f78" data-action="Deal Block" data-label="Go Walk Workout Walker (Women's)" data-dimension48="Go Walk Workout Walker (Women's)" data-dimension25="$117">View Deal</a></p></div><h3 class="article-body__section" id="section-skechers-deals-men-s"><span>Skechers deals (Men's)</span></h3><div class="product"><a data-dimension112="c1b22b96-cecb-11f1-8713-1f477ba8fa0d" data-action="Deal Block" data-label="Go Walk Arch Fit N-Joy Nate (Men's)" data-dimension48="Go Walk Arch Fit N-Joy Nate (Men's)" data-dimension25="$38" href="https://www.amazon.com/Skechers-Mens-N-Joy-Sneaker-White/dp/B0FDMS3F5K" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:54.53%;"><img id="m29EB9wmTKU2Ur4NSbtm8K" name="Go Walk Arch Fit N-Joy Nate (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/m29EB9wmTKU2Ur4NSbtm8K-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="379" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Mens-N-Joy-Sneaker-White/dp/B0FDMS3F5K" target="_blank" rel="nofollow" data-dimension112="c1b22b96-cecb-11f1-8713-1f477ba8fa0d" data-action="Deal Block" data-label="Go Walk Arch Fit N-Joy Nate (Men's)" data-dimension48="Go Walk Arch Fit N-Joy Nate (Men's)" data-dimension25="$38">Go Walk Arch Fit N-Joy Nate (Men's): was $78 now $38</a></strong><br />Need some extra support? These Skechers Arch Fit sneakers bring all that and more. The removeable insole absorbs shock and the upper is breathable and stretchy. I also love the sporty look these offer.<a class="view-deal button" href="https://www.amazon.com/Skechers-Mens-N-Joy-Sneaker-White/dp/B0FDMS3F5K" target="_blank" rel="nofollow" data-dimension112="c1b22b96-cecb-11f1-8713-1f477ba8fa0d" data-action="Deal Block" data-label="Go Walk Arch Fit N-Joy Nate (Men's)" data-dimension48="Go Walk Arch Fit N-Joy Nate (Men's)" data-dimension25="$38">View Deal</a></p></div><div class="product"><a data-dimension112="91313776-cec8-11f1-b0e9-efbb7a440890" data-action="Deal Block" data-label="Summits Louvin Slip-Ins (Men's)" data-dimension48="Summits Louvin Slip-Ins (Men's)" data-dimension25="$45" href="https://www.amazon.com/Skechers-Summits-Louvin-Loafer-Black/dp/B0864TFM51" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:65.61%;"><img id="jjR9bFWMb8tELv4o24E6Xm" name="Summits Louvin Slip-Ins (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jjR9bFWMb8tELv4o24E6Xm-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="456" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Summits-Louvin-Loafer-Black/dp/B0864TFM51" target="_blank" rel="nofollow" data-dimension112="91313776-cec8-11f1-b0e9-efbb7a440890" data-action="Deal Block" data-label="Summits Louvin Slip-Ins (Men's)" data-dimension48="Summits Louvin Slip-Ins (Men's)" data-dimension25="$45">Summits Louvin Slip-Ins (Men's): was $70 now $45</a></strong><br />Designed for athletics and light training, these Skechers are extremely comfortable — and their slip-on design means you don't have to tie your laces. They fit securely, too, and have soft memory foam insoles.<a class="view-deal button" href="https://www.amazon.com/Skechers-Summits-Louvin-Loafer-Black/dp/B0864TFM51" target="_blank" rel="nofollow" data-dimension112="91313776-cec8-11f1-b0e9-efbb7a440890" data-action="Deal Block" data-label="Summits Louvin Slip-Ins (Men's)" data-dimension48="Summits Louvin Slip-Ins (Men's)" data-dimension25="$45">View Deal</a></p></div><div class="product"><a data-dimension112="913137e4-cec8-11f1-9015-69214f380e55" data-action="Deal Block" data-label="Go Walk Max (Men's)" data-dimension48="Go Walk Max (Men's)" data-dimension25="$48" href="https://www.amazon.com/Skechers-Mens-Walk-Athletic-Walking/dp/B0F1Z7M7PT/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1065px;"><p class="vanilla-image-block" style="padding-top:56.06%;"><img id="hsosGofDzupcYyTW7KQq5m" name="61gxvfQj7xL._AC_SY625_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hsosGofDzupcYyTW7KQq5m-1920-80.jpg" mos="" align="middle" fullscreen="" width="1065" height="597" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Mens-Walk-Athletic-Walking/dp/B0F1Z7M7PT/" target="_blank" rel="nofollow" data-dimension112="913137e4-cec8-11f1-9015-69214f380e55" data-action="Deal Block" data-label="Go Walk Max (Men's)" data-dimension48="Go Walk Max (Men's)" data-dimension25="$48">Go Walk Max (Men's): was $49 now $48</a></strong><br />The Skechers Go Walk Max slip-on sneakers feature a super supportive insole that uses Goga Max Technology with high-rebound cushioning, along with an extra-padded heel for comfort. We rank them as one of the <a href="https://www.tomsguide.com/best-picks/best-skechers-shoes-in-year">best Skechers</a> you can buy.<a class="view-deal button" href="https://www.amazon.com/Skechers-Mens-Walk-Athletic-Walking/dp/B0F1Z7M7PT/" target="_blank" rel="nofollow" data-dimension112="913137e4-cec8-11f1-9015-69214f380e55" data-action="Deal Block" data-label="Go Walk Max (Men's)" data-dimension48="Go Walk Max (Men's)" data-dimension25="$48">View Deal</a></p></div><div class="product"><a data-dimension112="91313852-cec8-11f1-a518-7b3161f6fc33" data-action="Deal Block" data-label="Dighton Athletic Work Slip Resistant Food Service Shoe (Men's)" data-dimension48="Dighton Athletic Work Slip Resistant Food Service Shoe (Men's)" data-dimension25="$49" href="https://www.amazon.com/Skechers-Dighton-Black-Synthetic-Leather/dp/B01LY3WLXS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:50.50%;"><img id="ui9u7nTTsuRfPaNGRJ3e8g" name="Dighton Athletic Work Slip Resistant Food Service Shoe (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ui9u7nTTsuRfPaNGRJ3e8g-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="351" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Dighton-Black-Synthetic-Leather/dp/B01LY3WLXS" target="_blank" rel="nofollow" data-dimension112="91313852-cec8-11f1-a518-7b3161f6fc33" data-action="Deal Block" data-label="Dighton Athletic Work Slip Resistant Food Service Shoe (Men's)" data-dimension48="Dighton Athletic Work Slip Resistant Food Service Shoe (Men's)" data-dimension25="$49">Dighton Athletic Work Slip Resistant Food Service Shoe (Men's): was $65 now $49</a></strong><br />These Skechers have the look of a pair of smart leather shoes, but are durable, slip-resistant, and feature super-soft memory foam cushioning. They're built for long work days when you can't get off your feet, and will keep you feeling comfortable for hours.<a class="view-deal button" href="https://www.amazon.com/Skechers-Dighton-Black-Synthetic-Leather/dp/B01LY3WLXS" target="_blank" rel="nofollow" data-dimension112="91313852-cec8-11f1-a518-7b3161f6fc33" data-action="Deal Block" data-label="Dighton Athletic Work Slip Resistant Food Service Shoe (Men's)" data-dimension48="Dighton Athletic Work Slip Resistant Food Service Shoe (Men's)" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="9131391a-cec8-11f1-b570-a3feb6fe85af" data-action="Deal Block" data-label="Summits Key Pace Slip-ins (Men's)" data-dimension48="Summits Key Pace Slip-ins (Men's)" data-dimension25="$56" href="https://www.amazon.com/Skechers-Summits-Hands-Slip-Loafer/dp/B0H2K13WJL" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1143px;"><p class="vanilla-image-block" style="padding-top:60.80%;"><img id="d83wo5d5cEeEp8tWjiqKrC" name="716ignpBYCL._AC_SY695_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/d83wo5d5cEeEp8tWjiqKrC-1920-80.jpg" mos="" align="middle" fullscreen="" width="1143" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Summits-Hands-Slip-Loafer/dp/B0H2K13WJL" target="_blank" rel="nofollow" data-dimension112="9131391a-cec8-11f1-b570-a3feb6fe85af" data-action="Deal Block" data-label="Summits Key Pace Slip-ins (Men's)" data-dimension48="Summits Key Pace Slip-ins (Men's)" data-dimension25="$56">Summits Key Pace Slip-ins (Men's): was $72 now $56</a></strong><br />Another super-popular shoe, these men's slip-in sneakers have elastic stretch laces to save you from bending to tie your shoes. With a navy design that goes with everything, these are a seriously comfortable pair of sneakers at a great price. <a class="view-deal button" href="https://www.amazon.com/Skechers-Summits-Hands-Slip-Loafer/dp/B0H2K13WJL" target="_blank" rel="nofollow" data-dimension112="9131391a-cec8-11f1-b570-a3feb6fe85af" data-action="Deal Block" data-label="Summits Key Pace Slip-ins (Men's)" data-dimension48="Summits Key Pace Slip-ins (Men's)" data-dimension25="$56">View Deal</a></p></div><div class="product"><a data-dimension112="913138b6-cec8-11f1-ae7e-3910357b1187" data-action="Deal Block" data-label="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension48="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension25="$57" href="https://www.amazon.com/Skechers-Mens-Walk-Flex-Hands-Sneaker/dp/B0CFN8VR99" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:54.68%;"><img id="DsBvJExJKzNCdDFDnDXn3T" name="71y3Wpz-YFL._AC_SX695_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/DsBvJExJKzNCdDFDnDXn3T-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="380" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Mens-Walk-Flex-Hands-Sneaker/dp/B0CFN8VR99" target="_blank" rel="nofollow" data-dimension112="913138b6-cec8-11f1-ae7e-3910357b1187" data-action="Deal Block" data-label="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension48="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension25="$57">Slip-Ins Go Walk Flex Hands Up Sneaker: was $84 now $57</a></strong><br />A comfortable, reliable shoe, the Skechers Go Walk Flex Hands Up are now on sale starting from just $57. These come in a range of muted shades, meaning they're easy to pair with a range of outfits, and have Ultra Go cushioning to keep you light on your feet. Make sure to add a pair to your basket! <a class="view-deal button" href="https://www.amazon.com/Skechers-Mens-Walk-Flex-Hands-Sneaker/dp/B0CFN8VR99" target="_blank" rel="nofollow" data-dimension112="913138b6-cec8-11f1-ae7e-3910357b1187" data-action="Deal Block" data-label="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension48="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension25="$57">View Deal</a></p></div><div class="product"><a data-dimension112="c1b22c2c-cecb-11f1-ac8a-971b768153c7" data-action="Deal Block" data-label="Go Walk Max Cushioning Hyper Burst Zoltar (Men's)" data-dimension48="Go Walk Max Cushioning Hyper Burst Zoltar (Men's)" data-dimension25="$81" href="https://www.amazon.com/Skechers-Cushioning-Slip-Ins-Sneaker-Charcoal/dp/B0GY6FY26K" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:71.94%;"><img id="encAr2otkFXcfAuc4YmDdD" name="Go Walk Max Cushioning Hyper Burst Zoltar (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/encAr2otkFXcfAuc4YmDdD-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Cushioning-Slip-Ins-Sneaker-Charcoal/dp/B0GY6FY26K" target="_blank" rel="nofollow" data-dimension112="c1b22c2c-cecb-11f1-ac8a-971b768153c7" data-action="Deal Block" data-label="Go Walk Max Cushioning Hyper Burst Zoltar (Men's)" data-dimension48="Go Walk Max Cushioning Hyper Burst Zoltar (Men's)" data-dimension25="$81">Go Walk Max Cushioning Hyper Burst Zoltar (Men's): was $94 now $81</a></strong><br />These Skechers are simple, reliable and easy to style — but also provide tons of cushioning and energy to your walks. You also get a Goga Mat insole that keep the shoes breathable and lightweight.<a class="view-deal button" href="https://www.amazon.com/Skechers-Cushioning-Slip-Ins-Sneaker-Charcoal/dp/B0GY6FY26K" target="_blank" rel="nofollow" data-dimension112="c1b22c2c-cecb-11f1-ac8a-971b768153c7" data-action="Deal Block" data-label="Go Walk Max Cushioning Hyper Burst Zoltar (Men's)" data-dimension48="Go Walk Max Cushioning Hyper Burst Zoltar (Men's)" data-dimension25="$81">View Deal</a></p></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness/skechers-walking-shoes-are-up-to-61-percent-off-21-best-deals-on-sneakers-slip-ins-and-fall-boots</link>
                                                                            <description>
                            <![CDATA[ Amazon is offering huge discounts on Skechers! Check out the biggest savings you can shop this month. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">A42A42NSLXWmmyfv3MbiqT</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/dTR2fSKAShqNMLJJi6w5GH-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 23 Oct 2026 10:50:00 +0000</pubDate>                                                                                                                                <updated>Tue, 27 Oct 2026 12:47:06 +0000</updated>
                                                                                                                                            <category><![CDATA[Fitness]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                <author><![CDATA[ millie.daviswilliams@futurenet.com (Millie Davis-Williams) ]]></author>                    <dc:creator><![CDATA[ Millie Davis-Williams ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/WU6pa7hKuxs5ScCoqcXYWA-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Millie is a Deals Editor at Tom&#039;s Guide specializing in tech deals content. Based in London, Millie has spent a lifetime stubbornly refusing to pay full price on any possible purchase. She has years of searching for the best discounts on the latest and greatest phones, TVs and gadgets under her belt, and knows how to sort the best deals from the rest. Helping readers save on the products they want is her mission, whether it’s an Apple Watch or a new tablet.&lt;/p&gt;&lt;p&gt;Since working at Tom’s Guide, Millie has covered retail events like Prime Day, Black Friday and Cyber Monday extensively, meaning she knows the products readers are looking for and the best times of year to hit “purchase.”&lt;/p&gt;&lt;p&gt;When she’s not looking for discounts, Millie covers news and writes how-to articles about everything from phones, streaming devices, and headphones to apps and video games.&lt;/p&gt;&lt;p&gt;In her spare time, Millie enjoys reading, gaming on her Nintendo Switch and creating digital art. She’s also a fan of watching Disney movies and collecting plush (the latter having totally taken over her bedroom.)&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/dTR2fSKAShqNMLJJi6w5GH-1920-80.jpg">
                                                            <media:credit><![CDATA[Tom&#039;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Skechers Aero Razor running shoes]]></media:description>                                                            <media:text><![CDATA[Skechers Aero Razor running shoes]]></media:text>
                                <media:title type="plain"><![CDATA[Skechers Aero Razor running shoes]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/dTR2fSKAShqNMLJJi6w5GH-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Black Friday excitement is building! If you just can't wait, there's no need to worry — <a href="https://www.amazon.com/stores/page/37AAEB46-A955-4D92-957D-28A4B4B3FDE2" target="_blank" rel="nofollow">Amazon is offering huge price drops on Skechers</a> right now. Whether you're on the hunt for sneakers or cozy fall boots, I'm sharing all the best styles.</p><p>The shoe I'm most interested in right now is the <a href="https://www.amazon.com/Skechers-Sport-Womens-Slip-INS-Sneaker/dp/B0F3RMY5YF" target="_blank" rel="nofollow">Skechers Contour Foam Cozy Fit on sale from $50</a>. Not only are they the perfect comfy fall sneakers, they have one of the best color selections of any pair of Skechers you can buy right now.</p><p><strong>Note: </strong>Prices vary depending on the size and color you choose. Check out any different color options available in your size to find the best deals. For more, check out our <a href="https://www.tomsguide.com/coupons/amazon.com">Amazon promo codes</a>.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><strong></strong><a href="https://www.amazon.com/stores/page/37AAEB46-A955-4D92-957D-28A4B4B3FDE2" target="_blank" rel="nofollow"><strong>shop all Skechers deals at Amazon</strong></a></li><li><strong>Virtue Stunner (Women's): </strong><a href="https://www.amazon.com/Skechers-Womens-Sport-Active-Virtue/dp/B0FNCB7C3X/" target="_blank" rel="nofollow"><strong>was $58 now from $25</strong></a></li><li><strong>Go Walk Arch Fit N-Joy Nate (Men's): </strong><a href="https://www.amazon.com/Skechers-Mens-N-Joy-Sneaker-White/dp/B0FDMS3F5K" target="_blank" rel="nofollow"><strong>was $78 now from $38</strong></a></li><li><strong>Keepsakes Cozy - Cozy Cascade (Women's): </strong><a href="https://www.amazon.com/Skechers-Womens-KEEPSAKES-COZY-Chestnut/dp/B0GPD3LSTC" target="_blank" rel="nofollow"><strong>was $55 now from $41</strong></a></li><li><strong>Summits Louvin Slip-Ins (Men's): </strong><a href="https://www.amazon.com/Skechers-Summits-Louvin-Loafer-Black/dp/B0864TFM51" target="_blank" rel="nofollow"><strong>was $70 now from $45</strong></a></li><li><strong>Summits Key Pace Slip-ins (Men's): </strong><a href="https://www.amazon.com/Skechers-Summits-Hands-Slip-Loafer/dp/B0H2K13WJL" target="_blank" rel="nofollow"><strong>was $72 now from $56</strong></a></li><li><strong>Refine 2.0 Nora (Women's): </strong><a href="https://www.amazon.com/Skechers-Womens-Sport-Active-Refine/dp/B0G1PK31X7" target="_blank" rel="nofollow"><strong>was $84 now from $57</strong></a></li><li><strong>Segment Rilar (Men's): </strong><a href="https://www.amazon.com/Skechers-Segment-Rilar-Oxford-Brown/dp/B00I1JPY76" target="_blank" rel="nofollow"><strong>was $95 now from $59</strong></a></li><li><strong>Go Walk Max Cushioning Hyper Burst Zoltar (Men's): </strong><a href="https://www.amazon.com/Skechers-Cushioning-Slip-Ins-Sneaker-Charcoal/dp/B0GY6FY26K" target="_blank" rel="nofollow"><strong>was $94 now from $81</strong></a></li><li><strong>Aero Razor Running Shoes (Women's): </strong><a href="https://www.amazon.com/Skechers-Womens-Razor-Turquoise-Medium/dp/B0GVPVGG8C" target="_blank" rel="nofollow"><strong>was $140 now from $91</strong></a></li></ul><h3 class="article-body__section" id="section-skechers-deals-women-s"><span>Skechers deals (Women's)</span></h3><div class="product"><a data-dimension112="c1b22920-cecb-11f1-9f29-c55ce8bef84a" data-action="Deal Block" data-label="Virtue Stunner (Women's)" data-dimension48="Virtue Stunner (Women's)" data-dimension25="$25" href="https://www.amazon.com/Skechers-Womens-Sport-Active-Virtue/dp/B0FNC7ZZD1/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:64.32%;"><img id="fuQGoHerZPQAPL7bem8Pic" name="Virtue Stunner (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/fuQGoHerZPQAPL7bem8Pic-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="447" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Sport-Active-Virtue/dp/B0FNC7ZZD1/" target="_blank" rel="nofollow" data-dimension112="c1b22920-cecb-11f1-9f29-c55ce8bef84a" data-action="Deal Block" data-label="Virtue Stunner (Women's)" data-dimension48="Virtue Stunner (Women's)" data-dimension25="$25">Virtue Stunner (Women's): was $59 now $25</a></strong><br />This is another hefty Skechers discount that you'll have to act fast to grab, if they're available in your size. Currently on 57% off in Grey and 50% off in Natural, these super-simple, super-comfortable shoes have a soft knit upper and air-cooled memory foam insoles.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Sport-Active-Virtue/dp/B0FNC7ZZD1/" target="_blank" rel="nofollow" data-dimension112="c1b22920-cecb-11f1-9f29-c55ce8bef84a" data-action="Deal Block" data-label="Virtue Stunner (Women's)" data-dimension48="Virtue Stunner (Women's)" data-dimension25="$25">View Deal</a></p></div><div class="product"><a data-dimension112="913130c8-cec8-11f1-922c-ad116ac9d3cd" data-action="Deal Block" data-label="Refine 2.0 Nora (Women's)" data-dimension48="Refine 2.0 Nora (Women's)" data-dimension25="$35" href="https://www.amazon.com/Skechers-Womens-Sport-Active-Refine/dp/B0G1P5DSL6" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:66.91%;"><img id="XtYccaXnTY5XF946soUYSE" name="Refine 2.0 Nora (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XtYccaXnTY5XF946soUYSE-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="465" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Sport-Active-Refine/dp/B0G1P5DSL6" target="_blank" rel="nofollow" data-dimension112="913130c8-cec8-11f1-922c-ad116ac9d3cd" data-action="Deal Block" data-label="Refine 2.0 Nora (Women's)" data-dimension48="Refine 2.0 Nora (Women's)" data-dimension25="$35">Refine 2.0 Nora (Women's): was $84 now $35</a></strong><br />These Skechers have seen an impressive 58% discount when you check to apply the coupon on Amazon's page. Incredibly easy to wear, they feature a stretch knit upper, arch-fit insoles and are machine washable. <a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Sport-Active-Refine/dp/B0G1P5DSL6" target="_blank" rel="nofollow" data-dimension112="913130c8-cec8-11f1-922c-ad116ac9d3cd" data-action="Deal Block" data-label="Refine 2.0 Nora (Women's)" data-dimension48="Refine 2.0 Nora (Women's)" data-dimension25="$35">View Deal</a></p></div><div class="product"><a data-dimension112="91313136-cec8-11f1-8ab9-7b04dd6482f5" data-action="Deal Block" data-label="Bobs Keepsakes Lite Slipper (Women's)" data-dimension48="Bobs Keepsakes Lite Slipper (Women's)" data-dimension25="$39" href="https://www.amazon.com/Skechers-Keepsakes-Lite-Cozy-Slipper-Chestnut/dp/B0BX22T5PF/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1181px;"><p class="vanilla-image-block" style="padding-top:58.85%;"><img id="ut3KQ3LGhZKe4rhieo9nsK" name="719iDVut31L._AC_SY695" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ut3KQ3LGhZKe4rhieo9nsK-1920-80.png" mos="" align="middle" fullscreen="" width="1181" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Keepsakes-Lite-Cozy-Slipper-Chestnut/dp/B0BX22T5PF/" target="_blank" rel="nofollow" data-dimension112="91313136-cec8-11f1-8ab9-7b04dd6482f5" data-action="Deal Block" data-label="Bobs Keepsakes Lite Slipper (Women's)" data-dimension48="Bobs Keepsakes Lite Slipper (Women's)" data-dimension25="$39">Bobs Keepsakes Lite Slipper (Women's): was $51 now $39</a></strong><br />Get yourself prepared for winter extra early with these cozy, lined Skechers slippers. With memory-foam insoles, faux fur trim and traction outer sole, these snug slippers will keep you warm, no matter where you wear them.  <a class="view-deal button" href="https://www.amazon.com/Skechers-Keepsakes-Lite-Cozy-Slipper-Chestnut/dp/B0BX22T5PF/" target="_blank" rel="nofollow" data-dimension112="91313136-cec8-11f1-8ab9-7b04dd6482f5" data-action="Deal Block" data-label="Bobs Keepsakes Lite Slipper (Women's)" data-dimension48="Bobs Keepsakes Lite Slipper (Women's)" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="c1b229ac-cecb-11f1-a96f-d55b9dd5dd35" data-action="Deal Block" data-label="Keepsakes Cozy - Cozy Cascade (Women's)" data-dimension48="Keepsakes Cozy - Cozy Cascade (Women's)" data-dimension25="$41" href="https://www.amazon.com/Skechers-Womens-KEEPSAKES-COZY-Chestnut/dp/B0GPMGKPT8" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:55.68%;"><img id="hYSZfU9nU4nzZJ6fSLnpeZ" name="Keepsakes Cozy - Cozy Cascade (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hYSZfU9nU4nzZJ6fSLnpeZ-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="387" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-KEEPSAKES-COZY-Chestnut/dp/B0GPMGKPT8" target="_blank" rel="nofollow" data-dimension112="c1b229ac-cecb-11f1-a96f-d55b9dd5dd35" data-action="Deal Block" data-label="Keepsakes Cozy - Cozy Cascade (Women's)" data-dimension48="Keepsakes Cozy - Cozy Cascade (Women's)" data-dimension25="$41">Keepsakes Cozy - Cozy Cascade (Women's): was $55 now $41</a></strong><br />You can't have enough cozy pairs of slippers, especially this time of year. These Skechers stand out for their pretty embroidered design on the cuff, and have a soft fuzzy lining — plus Skechers memory foam.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-KEEPSAKES-COZY-Chestnut/dp/B0GPMGKPT8" target="_blank" rel="nofollow" data-dimension112="c1b229ac-cecb-11f1-a96f-d55b9dd5dd35" data-action="Deal Block" data-label="Keepsakes Cozy - Cozy Cascade (Women's)" data-dimension48="Keepsakes Cozy - Cozy Cascade (Women's)" data-dimension25="$41">View Deal</a></p></div><div class="product"><a data-dimension112="91313352-cec8-11f1-b43d-51f87ac772f8" data-action="Deal Block" data-label="Contour Foam Cozy Fit Slip-Ins (Women's)" data-dimension48="Contour Foam Cozy Fit Slip-Ins (Women's)" data-dimension25="$50" href="https://www.amazon.com/Skechers-Sport-Womens-Slip-INS-Sneaker/dp/B0F3RMY5YF" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:66.91%;"><img id="Upd6k99BCo75ngNtEoAdxJ" name="Contour Foam Cozy Fit Slip-Ins (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Upd6k99BCo75ngNtEoAdxJ-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="465" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Sport-Womens-Slip-INS-Sneaker/dp/B0F3RMY5YF" target="_blank" rel="nofollow" data-dimension112="91313352-cec8-11f1-b43d-51f87ac772f8" data-action="Deal Block" data-label="Contour Foam Cozy Fit Slip-Ins (Women's)" data-dimension48="Contour Foam Cozy Fit Slip-Ins (Women's)" data-dimension25="$50">Contour Foam Cozy Fit Slip-Ins (Women's): was $89 now $50</a></strong><br />I love the look of these Skechers, because of the two-tone design — you can get them in white paired with a bunch of other accent colors. As well as looking great, they have a Contour Foam midsole that adapts to your foot's shape, making them some of the comfiest-feeling shoes around.<a class="view-deal button" href="https://www.amazon.com/Skechers-Sport-Womens-Slip-INS-Sneaker/dp/B0F3RMY5YF" target="_blank" rel="nofollow" data-dimension112="91313352-cec8-11f1-b43d-51f87ac772f8" data-action="Deal Block" data-label="Contour Foam Cozy Fit Slip-Ins (Women's)" data-dimension48="Contour Foam Cozy Fit Slip-Ins (Women's)" data-dimension25="$50">View Deal</a></p></div><div class="product"><a data-dimension112="c1b22a24-cecb-11f1-818f-fffaa8c68890" data-action="Deal Block" data-label="Keepsakes Cozy Cozy Mini Slip-Ins Boot (Women's)" data-dimension48="Keepsakes Cozy Cozy Mini Slip-Ins Boot (Women's)" data-dimension25="$52" href="https://www.amazon.com/Skechers-Womens-KEEPSAKES-COZY-Slip-Ins/dp/B0GZJHW6DJ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:72.23%;"><img id="C6vf8hr9LiPZZL7EueMWZH" name="Keepsakes Cozy Cozy Mini Slip-Ins Boot (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/C6vf8hr9LiPZZL7EueMWZH-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="502" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-KEEPSAKES-COZY-Slip-Ins/dp/B0GZJHW6DJ" target="_blank" rel="nofollow" data-dimension112="c1b22a24-cecb-11f1-818f-fffaa8c68890" data-action="Deal Block" data-label="Keepsakes Cozy Cozy Mini Slip-Ins Boot (Women's)" data-dimension48="Keepsakes Cozy Cozy Mini Slip-Ins Boot (Women's)" data-dimension25="$52">Keepsakes Cozy Cozy Mini Slip-Ins Boot (Women's): was $75 now $52</a></strong><br />Double the cozy! Skechers seems to have taken some style cues from Ugg here with a slip-in, wool-lined boot. The heart-shaped charm on the side is a nice touch.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-KEEPSAKES-COZY-Slip-Ins/dp/B0GZJHW6DJ" target="_blank" rel="nofollow" data-dimension112="c1b22a24-cecb-11f1-818f-fffaa8c68890" data-action="Deal Block" data-label="Keepsakes Cozy Cozy Mini Slip-Ins Boot (Women's)" data-dimension48="Keepsakes Cozy Cozy Mini Slip-Ins Boot (Women's)" data-dimension25="$52">View Deal</a></p></div><div class="product"><a data-dimension112="91313488-cec8-11f1-969e-15c257f47827" data-action="Deal Block" data-label="Uno - Champagne &amp; Roses (Women's)" data-dimension48="Uno - Champagne &amp; Roses (Women's)" data-dimension25="$53" href="https://www.amazon.com/Skechers-Street-Womens-UNO-Champagne/dp/B0FN6Y36CP" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:73.09%;"><img id="k9WB77eyZDmMW3XwNPTVym" name="Uno - Champagne &amp; Roses (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/k9WB77eyZDmMW3XwNPTVym-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="508" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Street-Womens-UNO-Champagne/dp/B0FN6Y36CP" target="_blank" rel="nofollow" data-dimension112="91313488-cec8-11f1-969e-15c257f47827" data-action="Deal Block" data-label="Uno - Champagne &amp; Roses (Women's)" data-dimension48="Uno - Champagne &amp; Roses (Women's)" data-dimension25="$53">Uno - Champagne &amp; Roses (Women's): was $83 now $53</a></strong><br />Need a practical gift? These shoes are perfect for the job since they look super stylish and are extremely comfortable. The rose petal decor further elevates the look.<a class="view-deal button" href="https://www.amazon.com/Skechers-Street-Womens-UNO-Champagne/dp/B0FN6Y36CP" target="_blank" rel="nofollow" data-dimension112="91313488-cec8-11f1-969e-15c257f47827" data-action="Deal Block" data-label="Uno - Champagne &amp; Roses (Women's)" data-dimension48="Uno - Champagne &amp; Roses (Women's)" data-dimension25="$53">View Deal</a></p></div><div class="product"><a data-dimension112="c1b22a9c-cecb-11f1-a4d1-d3fbd5fd194c" data-action="Deal Block" data-label="Glide-Step Pro Soft Mirage (Women's)" data-dimension48="Glide-Step Pro Soft Mirage (Women's)" data-dimension25="$61" href="https://www.amazon.com/Skechers-Womens-Glide-Step-Soft-Mirage/dp/B0HMJWHM8D" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:70.36%;"><img id="gENhFcxWPfR5eGzmaeeMrZ" name="Glide-Step Pro Soft Mirage (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gENhFcxWPfR5eGzmaeeMrZ-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="489" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Glide-Step-Soft-Mirage/dp/B0HMJWHM8D" target="_blank" rel="nofollow" data-dimension112="c1b22a9c-cecb-11f1-a4d1-d3fbd5fd194c" data-action="Deal Block" data-label="Glide-Step Pro Soft Mirage (Women's)" data-dimension48="Glide-Step Pro Soft Mirage (Women's)" data-dimension25="$61">Glide-Step Pro Soft Mirage (Women's): was $78 now $61</a></strong><br />The Skechers Glide-Step offer improved movement and momentum, making every step feel lighter and more energetic. These Soft Mirage sneakers deliver all that as well as a sleek, understated style.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Glide-Step-Soft-Mirage/dp/B0HMJWHM8D" target="_blank" rel="nofollow" data-dimension112="c1b22a9c-cecb-11f1-a4d1-d3fbd5fd194c" data-action="Deal Block" data-label="Glide-Step Pro Soft Mirage (Women's)" data-dimension48="Glide-Step Pro Soft Mirage (Women's)" data-dimension25="$61">View Deal</a></p></div><div class="product star-deal"><a data-dimension112="91313424-cec8-11f1-b781-a32374e2b11a" data-action="Star Deal Block" data-label="Go Run Elevate 2.0 Sneaker (Women's)" data-dimension48="Go Run Elevate 2.0 Sneaker (Women's)" data-dimension25="$64" href="https://www.amazon.com/Skechers-Womens-Elevate-Sneaker-Black/dp/B0CNP8Z6FM" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:52.81%;"><img id="vCHwenty55qSsiSaaAhmLh" name="Go Run Elevate 2.0 Sneaker (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vCHwenty55qSsiSaaAhmLh-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="367" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Elevate-Sneaker-Black/dp/B0CNP8Z6FM" target="_blank" rel="nofollow" data-dimension112="91313424-cec8-11f1-b781-a32374e2b11a" data-action="Star Deal Block" data-label="Go Run Elevate 2.0 Sneaker (Women's)" data-dimension48="Go Run Elevate 2.0 Sneaker (Women's)" data-dimension25="$64">Go Run Elevate 2.0 Sneaker (Women's): was $85 now $64</a></strong><br />If you're hitting the road, these Skechers are an excellent choice. Our <a href="https://www.tomsguide.com/wellness/running/skechers-go-run-elevate-2-review">Skechers Go Run Elevate 2.0 review</a> said that these are great for beginner runners thanks to their affordable price point, bouncy and propulsive soles and breathable design. These sneakers were originally priced at $85, but now you can get them for $64.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Elevate-Sneaker-Black/dp/B0CNP8Z6FM" target="_blank" rel="nofollow" data-dimension112="91313424-cec8-11f1-b781-a32374e2b11a" data-action="Star Deal Block" data-label="Go Run Elevate 2.0 Sneaker (Women's)" data-dimension48="Go Run Elevate 2.0 Sneaker (Women's)" data-dimension25="$64">View Deal</a></p></div><div class="product"><a data-dimension112="c1b22b00-cecb-11f1-9b5f-dbddd6d2807b" data-action="Deal Block" data-label="Easy Going - Warm Occasion - Hands Free Slip-ins (Women's)" data-dimension48="Easy Going - Warm Occasion - Hands Free Slip-ins (Women's)" data-dimension25="$80" href="https://www.amazon.com/Skechers-Womens-EASY-GOING-Chocolate/dp/B0GPD6P9F9" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:77.99%;"><img id="6SS6HJuer92iBVzNnRbUbU" name="Easy Going - Warm Occasion - Hands Free Slip-ins (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/6SS6HJuer92iBVzNnRbUbU-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="542" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-EASY-GOING-Chocolate/dp/B0GPD6P9F9" target="_blank" rel="nofollow" data-dimension112="c1b22b00-cecb-11f1-9b5f-dbddd6d2807b" data-action="Deal Block" data-label="Easy Going - Warm Occasion - Hands Free Slip-ins (Women's)" data-dimension48="Easy Going - Warm Occasion - Hands Free Slip-ins (Women's)" data-dimension25="$80">Easy Going - Warm Occasion - Hands Free Slip-ins (Women's): was $95 now $80</a></strong><br />These cozy Skechers boots are basically an essential this season. They slip on easily and bring both cushioning and warmth that you won't want to go without on your fall walks.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-EASY-GOING-Chocolate/dp/B0GPD6P9F9" target="_blank" rel="nofollow" data-dimension112="c1b22b00-cecb-11f1-9b5f-dbddd6d2807b" data-action="Deal Block" data-label="Easy Going - Warm Occasion - Hands Free Slip-ins (Women's)" data-dimension48="Easy Going - Warm Occasion - Hands Free Slip-ins (Women's)" data-dimension25="$80">View Deal</a></p></div><div class="product"><a data-dimension112="913134f6-cec8-11f1-8420-c503bd559b16" data-action="Deal Block" data-label="Max Cushioning Elite 2.0 (Women's)" data-dimension48="Max Cushioning Elite 2.0 (Women's)" data-dimension25="$84" href="https://www.amazon.com/Skechers-Cushioning-Elite-Natural-Pink/dp/B0BZ93LKDQ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:63.60%;"><img id="DDNtxm7NqaHbqokBvRhcxe" name="Skechers Max Cushioning Elite 2.0" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/DDNtxm7NqaHbqokBvRhcxe-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="442" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Cushioning-Elite-Natural-Pink/dp/B0BZ93LKDQ" target="_blank" rel="nofollow" data-dimension112="913134f6-cec8-11f1-8420-c503bd559b16" data-action="Deal Block" data-label="Max Cushioning Elite 2.0 (Women's)" data-dimension48="Max Cushioning Elite 2.0 (Women's)" data-dimension25="$84">Max Cushioning Elite 2.0 (Women's): was $100 now $84</a></strong><br />These are a pair of comfortable, max-cushioned shoes, best suited to easy miles and long runs. They are hailed as cheaper dupes for the <a href="https://www.tomsguide.com/reviews/hoka-clifton-9">Hoka Clifton 9</a> trainers, without the price tag. Best suited to beginners, or runners looking for a plush shoe to wear for easy miles and long walks, these are a decent option. Read our <a href="https://www.tomsguide.com/wellness/fitness/skechers-max-cushioning-elite-2-0-review">Skechers Max Cushioning Elite 2.0 review</a> for all the info.<a class="view-deal button" href="https://www.amazon.com/Skechers-Cushioning-Elite-Natural-Pink/dp/B0BZ93LKDQ" target="_blank" rel="nofollow" data-dimension112="913134f6-cec8-11f1-8420-c503bd559b16" data-action="Deal Block" data-label="Max Cushioning Elite 2.0 (Women's)" data-dimension48="Max Cushioning Elite 2.0 (Women's)" data-dimension25="$84">View Deal</a></p></div><div class="product"><a data-dimension112="9131362c-cec8-11f1-8251-7fa7af1c2d72" data-action="Deal Block" data-label="Max Cushioning Endeavour Pace Rhythm (Women's)" data-dimension48="Max Cushioning Endeavour Pace Rhythm (Women's)" data-dimension25="$85" href="https://www.amazon.com/Skechers-Womens-Slip-Ins-Cushioning-Endeavour/dp/B0GY6J4H4G" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:59.57%;"><img id="gX8x3dDgKEF8A5TFTT62gg" name="Max Cushioning Endeavour Pace Rhythm (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gX8x3dDgKEF8A5TFTT62gg-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="414" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Slip-Ins-Cushioning-Endeavour/dp/B0GY6J4H4G" target="_blank" rel="nofollow" data-dimension112="9131362c-cec8-11f1-8251-7fa7af1c2d72" data-action="Deal Block" data-label="Max Cushioning Endeavour Pace Rhythm (Women's)" data-dimension48="Max Cushioning Endeavour Pace Rhythm (Women's)" data-dimension25="$85">Max Cushioning Endeavour Pace Rhythm (Women's): was $105 now $85</a></strong><br />Though they're on the expensive side of Skechers' offerings, these running shoes make a statement and offer tons of comfortable cushioning. The Goga Mat insole propels you forwards and the rocker shape helps your steps transition naturally.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Slip-Ins-Cushioning-Endeavour/dp/B0GY6J4H4G" target="_blank" rel="nofollow" data-dimension112="9131362c-cec8-11f1-8251-7fa7af1c2d72" data-action="Deal Block" data-label="Max Cushioning Endeavour Pace Rhythm (Women's)" data-dimension48="Max Cushioning Endeavour Pace Rhythm (Women's)" data-dimension25="$85">View Deal</a></p></div><div class="product"><a data-dimension112="913135be-cec8-11f1-af62-7fe0a945fa4b" data-action="Deal Block" data-label="Aero Razor Running Shoes (Women's)" data-dimension48="Aero Razor Running Shoes (Women's)" data-dimension25="$91" href="https://www.amazon.com/Skechers-Womens-Razor-Turquoise-Medium/dp/B0GVPVGG8C" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:56.69%;"><img id="aqUWsueeM3Z3zz4bY64ro4" name="Aero Razor Running Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/aqUWsueeM3Z3zz4bY64ro4-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="394" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Razor-Turquoise-Medium/dp/B0GVPVGG8C" target="_blank" rel="nofollow" data-dimension112="913135be-cec8-11f1-af62-7fe0a945fa4b" data-action="Deal Block" data-label="Aero Razor Running Shoes (Women's)" data-dimension48="Aero Razor Running Shoes (Women's)" data-dimension25="$91">Aero Razor Running Shoes (Women's): was $140 now $91</a></strong><br />We loved these shoes in our <a href="https://www.tomsguide.com/wellness/running/skechers-aero-razor-review">Skechers Aero Razor review</a>! Our testers said this is a great pair of lightweight shoes for runners who want to pick up speed. You'll find more cushioning elsewhere, but these running shoes bring a super energetic feel to every step you take.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Razor-Turquoise-Medium/dp/B0GVPVGG8C" target="_blank" rel="nofollow" data-dimension112="913135be-cec8-11f1-af62-7fe0a945fa4b" data-action="Deal Block" data-label="Aero Razor Running Shoes (Women's)" data-dimension48="Aero Razor Running Shoes (Women's)" data-dimension25="$91">View Deal</a></p></div><div class="product"><a data-dimension112="9131369a-cec8-11f1-b1eb-93110f318f78" data-action="Deal Block" data-label="Go Walk Workout Walker (Women's)" data-dimension48="Go Walk Workout Walker (Women's)" data-dimension25="$117" href="https://www.amazon.com/Skechers-Womens-Slip-Ins-Workout-Walker/dp/B0GTRTRK9P" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:59.42%;"><img id="g6Fbk2tgHp3unLKa8Gkd3g" name="Go Walk Workout Walker (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/g6Fbk2tgHp3unLKa8Gkd3g-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="413" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Slip-Ins-Workout-Walker/dp/B0GTRTRK9P" target="_blank" rel="nofollow" data-dimension112="9131369a-cec8-11f1-b1eb-93110f318f78" data-action="Deal Block" data-label="Go Walk Workout Walker (Women's)" data-dimension48="Go Walk Workout Walker (Women's)" data-dimension25="$117">Go Walk Workout Walker (Women's): was $135 now $117</a></strong><br />One of the <a href="https://www.tomsguide.com/best-picks/best-skechers-shoes-in-year">best Skechers</a> we've tested, the <a href="https://www.tomsguide.com/reviews/skechers-go-walk-workout-walker">Skechers Go Walk Workout Walker</a>, has gotten a new look. I love the new color options — plus you get a slip-in fit, super-soft cushioning and air cooled memory foam on board.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Slip-Ins-Workout-Walker/dp/B0GTRTRK9P" target="_blank" rel="nofollow" data-dimension112="9131369a-cec8-11f1-b1eb-93110f318f78" data-action="Deal Block" data-label="Go Walk Workout Walker (Women's)" data-dimension48="Go Walk Workout Walker (Women's)" data-dimension25="$117">View Deal</a></p></div><h3 class="article-body__section" id="section-skechers-deals-men-s"><span>Skechers deals (Men's)</span></h3><div class="product"><a data-dimension112="c1b22b96-cecb-11f1-8713-1f477ba8fa0d" data-action="Deal Block" data-label="Go Walk Arch Fit N-Joy Nate (Men's)" data-dimension48="Go Walk Arch Fit N-Joy Nate (Men's)" data-dimension25="$38" href="https://www.amazon.com/Skechers-Mens-N-Joy-Sneaker-White/dp/B0FDMS3F5K" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:54.53%;"><img id="m29EB9wmTKU2Ur4NSbtm8K" name="Go Walk Arch Fit N-Joy Nate (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/m29EB9wmTKU2Ur4NSbtm8K-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="379" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Mens-N-Joy-Sneaker-White/dp/B0FDMS3F5K" target="_blank" rel="nofollow" data-dimension112="c1b22b96-cecb-11f1-8713-1f477ba8fa0d" data-action="Deal Block" data-label="Go Walk Arch Fit N-Joy Nate (Men's)" data-dimension48="Go Walk Arch Fit N-Joy Nate (Men's)" data-dimension25="$38">Go Walk Arch Fit N-Joy Nate (Men's): was $78 now $38</a></strong><br />Need some extra support? These Skechers Arch Fit sneakers bring all that and more. The removeable insole absorbs shock and the upper is breathable and stretchy. I also love the sporty look these offer.<a class="view-deal button" href="https://www.amazon.com/Skechers-Mens-N-Joy-Sneaker-White/dp/B0FDMS3F5K" target="_blank" rel="nofollow" data-dimension112="c1b22b96-cecb-11f1-8713-1f477ba8fa0d" data-action="Deal Block" data-label="Go Walk Arch Fit N-Joy Nate (Men's)" data-dimension48="Go Walk Arch Fit N-Joy Nate (Men's)" data-dimension25="$38">View Deal</a></p></div><div class="product"><a data-dimension112="91313776-cec8-11f1-b0e9-efbb7a440890" data-action="Deal Block" data-label="Summits Louvin Slip-Ins (Men's)" data-dimension48="Summits Louvin Slip-Ins (Men's)" data-dimension25="$45" href="https://www.amazon.com/Skechers-Summits-Louvin-Loafer-Black/dp/B0864TFM51" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:65.61%;"><img id="jjR9bFWMb8tELv4o24E6Xm" name="Summits Louvin Slip-Ins (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jjR9bFWMb8tELv4o24E6Xm-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="456" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Summits-Louvin-Loafer-Black/dp/B0864TFM51" target="_blank" rel="nofollow" data-dimension112="91313776-cec8-11f1-b0e9-efbb7a440890" data-action="Deal Block" data-label="Summits Louvin Slip-Ins (Men's)" data-dimension48="Summits Louvin Slip-Ins (Men's)" data-dimension25="$45">Summits Louvin Slip-Ins (Men's): was $70 now $45</a></strong><br />Designed for athletics and light training, these Skechers are extremely comfortable — and their slip-on design means you don't have to tie your laces. They fit securely, too, and have soft memory foam insoles.<a class="view-deal button" href="https://www.amazon.com/Skechers-Summits-Louvin-Loafer-Black/dp/B0864TFM51" target="_blank" rel="nofollow" data-dimension112="91313776-cec8-11f1-b0e9-efbb7a440890" data-action="Deal Block" data-label="Summits Louvin Slip-Ins (Men's)" data-dimension48="Summits Louvin Slip-Ins (Men's)" data-dimension25="$45">View Deal</a></p></div><div class="product"><a data-dimension112="913137e4-cec8-11f1-9015-69214f380e55" data-action="Deal Block" data-label="Go Walk Max (Men's)" data-dimension48="Go Walk Max (Men's)" data-dimension25="$48" href="https://www.amazon.com/Skechers-Mens-Walk-Athletic-Walking/dp/B0F1Z7M7PT/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1065px;"><p class="vanilla-image-block" style="padding-top:56.06%;"><img id="hsosGofDzupcYyTW7KQq5m" name="61gxvfQj7xL._AC_SY625_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hsosGofDzupcYyTW7KQq5m-1920-80.jpg" mos="" align="middle" fullscreen="" width="1065" height="597" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Mens-Walk-Athletic-Walking/dp/B0F1Z7M7PT/" target="_blank" rel="nofollow" data-dimension112="913137e4-cec8-11f1-9015-69214f380e55" data-action="Deal Block" data-label="Go Walk Max (Men's)" data-dimension48="Go Walk Max (Men's)" data-dimension25="$48">Go Walk Max (Men's): was $49 now $48</a></strong><br />The Skechers Go Walk Max slip-on sneakers feature a super supportive insole that uses Goga Max Technology with high-rebound cushioning, along with an extra-padded heel for comfort. We rank them as one of the <a href="https://www.tomsguide.com/best-picks/best-skechers-shoes-in-year">best Skechers</a> you can buy.<a class="view-deal button" href="https://www.amazon.com/Skechers-Mens-Walk-Athletic-Walking/dp/B0F1Z7M7PT/" target="_blank" rel="nofollow" data-dimension112="913137e4-cec8-11f1-9015-69214f380e55" data-action="Deal Block" data-label="Go Walk Max (Men's)" data-dimension48="Go Walk Max (Men's)" data-dimension25="$48">View Deal</a></p></div><div class="product"><a data-dimension112="91313852-cec8-11f1-a518-7b3161f6fc33" data-action="Deal Block" data-label="Dighton Athletic Work Slip Resistant Food Service Shoe (Men's)" data-dimension48="Dighton Athletic Work Slip Resistant Food Service Shoe (Men's)" data-dimension25="$49" href="https://www.amazon.com/Skechers-Dighton-Black-Synthetic-Leather/dp/B01LY3WLXS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:50.50%;"><img id="ui9u7nTTsuRfPaNGRJ3e8g" name="Dighton Athletic Work Slip Resistant Food Service Shoe (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ui9u7nTTsuRfPaNGRJ3e8g-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="351" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Dighton-Black-Synthetic-Leather/dp/B01LY3WLXS" target="_blank" rel="nofollow" data-dimension112="91313852-cec8-11f1-a518-7b3161f6fc33" data-action="Deal Block" data-label="Dighton Athletic Work Slip Resistant Food Service Shoe (Men's)" data-dimension48="Dighton Athletic Work Slip Resistant Food Service Shoe (Men's)" data-dimension25="$49">Dighton Athletic Work Slip Resistant Food Service Shoe (Men's): was $65 now $49</a></strong><br />These Skechers have the look of a pair of smart leather shoes, but are durable, slip-resistant, and feature super-soft memory foam cushioning. They're built for long work days when you can't get off your feet, and will keep you feeling comfortable for hours.<a class="view-deal button" href="https://www.amazon.com/Skechers-Dighton-Black-Synthetic-Leather/dp/B01LY3WLXS" target="_blank" rel="nofollow" data-dimension112="91313852-cec8-11f1-a518-7b3161f6fc33" data-action="Deal Block" data-label="Dighton Athletic Work Slip Resistant Food Service Shoe (Men's)" data-dimension48="Dighton Athletic Work Slip Resistant Food Service Shoe (Men's)" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="9131391a-cec8-11f1-b570-a3feb6fe85af" data-action="Deal Block" data-label="Summits Key Pace Slip-ins (Men's)" data-dimension48="Summits Key Pace Slip-ins (Men's)" data-dimension25="$56" href="https://www.amazon.com/Skechers-Summits-Hands-Slip-Loafer/dp/B0H2K13WJL" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1143px;"><p class="vanilla-image-block" style="padding-top:60.80%;"><img id="d83wo5d5cEeEp8tWjiqKrC" name="716ignpBYCL._AC_SY695_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/d83wo5d5cEeEp8tWjiqKrC-1920-80.jpg" mos="" align="middle" fullscreen="" width="1143" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Summits-Hands-Slip-Loafer/dp/B0H2K13WJL" target="_blank" rel="nofollow" data-dimension112="9131391a-cec8-11f1-b570-a3feb6fe85af" data-action="Deal Block" data-label="Summits Key Pace Slip-ins (Men's)" data-dimension48="Summits Key Pace Slip-ins (Men's)" data-dimension25="$56">Summits Key Pace Slip-ins (Men's): was $72 now $56</a></strong><br />Another super-popular shoe, these men's slip-in sneakers have elastic stretch laces to save you from bending to tie your shoes. With a navy design that goes with everything, these are a seriously comfortable pair of sneakers at a great price. <a class="view-deal button" href="https://www.amazon.com/Skechers-Summits-Hands-Slip-Loafer/dp/B0H2K13WJL" target="_blank" rel="nofollow" data-dimension112="9131391a-cec8-11f1-b570-a3feb6fe85af" data-action="Deal Block" data-label="Summits Key Pace Slip-ins (Men's)" data-dimension48="Summits Key Pace Slip-ins (Men's)" data-dimension25="$56">View Deal</a></p></div><div class="product"><a data-dimension112="913138b6-cec8-11f1-ae7e-3910357b1187" data-action="Deal Block" data-label="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension48="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension25="$57" href="https://www.amazon.com/Skechers-Mens-Walk-Flex-Hands-Sneaker/dp/B0CFN8VR99" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:54.68%;"><img id="DsBvJExJKzNCdDFDnDXn3T" name="71y3Wpz-YFL._AC_SX695_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/DsBvJExJKzNCdDFDnDXn3T-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="380" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Mens-Walk-Flex-Hands-Sneaker/dp/B0CFN8VR99" target="_blank" rel="nofollow" data-dimension112="913138b6-cec8-11f1-ae7e-3910357b1187" data-action="Deal Block" data-label="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension48="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension25="$57">Slip-Ins Go Walk Flex Hands Up Sneaker: was $84 now $57</a></strong><br />A comfortable, reliable shoe, the Skechers Go Walk Flex Hands Up are now on sale starting from just $57. These come in a range of muted shades, meaning they're easy to pair with a range of outfits, and have Ultra Go cushioning to keep you light on your feet. Make sure to add a pair to your basket! <a class="view-deal button" href="https://www.amazon.com/Skechers-Mens-Walk-Flex-Hands-Sneaker/dp/B0CFN8VR99" target="_blank" rel="nofollow" data-dimension112="913138b6-cec8-11f1-ae7e-3910357b1187" data-action="Deal Block" data-label="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension48="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension25="$57">View Deal</a></p></div><div class="product"><a data-dimension112="c1b22c2c-cecb-11f1-ac8a-971b768153c7" data-action="Deal Block" data-label="Go Walk Max Cushioning Hyper Burst Zoltar (Men's)" data-dimension48="Go Walk Max Cushioning Hyper Burst Zoltar (Men's)" data-dimension25="$81" href="https://www.amazon.com/Skechers-Cushioning-Slip-Ins-Sneaker-Charcoal/dp/B0GY6FY26K" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:71.94%;"><img id="encAr2otkFXcfAuc4YmDdD" name="Go Walk Max Cushioning Hyper Burst Zoltar (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/encAr2otkFXcfAuc4YmDdD-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Cushioning-Slip-Ins-Sneaker-Charcoal/dp/B0GY6FY26K" target="_blank" rel="nofollow" data-dimension112="c1b22c2c-cecb-11f1-ac8a-971b768153c7" data-action="Deal Block" data-label="Go Walk Max Cushioning Hyper Burst Zoltar (Men's)" data-dimension48="Go Walk Max Cushioning Hyper Burst Zoltar (Men's)" data-dimension25="$81">Go Walk Max Cushioning Hyper Burst Zoltar (Men's): was $94 now $81</a></strong><br />These Skechers are simple, reliable and easy to style — but also provide tons of cushioning and energy to your walks. You also get a Goga Mat insole that keep the shoes breathable and lightweight.<a class="view-deal button" href="https://www.amazon.com/Skechers-Cushioning-Slip-Ins-Sneaker-Charcoal/dp/B0GY6FY26K" target="_blank" rel="nofollow" data-dimension112="c1b22c2c-cecb-11f1-ac8a-971b768153c7" data-action="Deal Block" data-label="Go Walk Max Cushioning Hyper Burst Zoltar (Men's)" data-dimension48="Go Walk Max Cushioning Hyper Burst Zoltar (Men's)" data-dimension25="$81">View Deal</a></p></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I’ve been running on the WalkingPad G5i treadmill and its tri-fold design is perfect for small homes ]]></title>
                                                                                                <dc:content><![CDATA[ <div  class="fancy-box"><div class="fancy_box-title">WalkindPad G5i Specs</div><div class="fancy_box_body"><p class="fancy-box__body-text"><strong>Dimensions (unfolded): </strong>64.6 x 33.4 x 43.4 inches<br /><strong>Dimensions (folded)</strong>: 45.7 x 33.4 x 10.2 inches<br /><strong>Running surface: </strong>51.2 x 19.7 inches<br /><strong>Weight: </strong>150lbs<br /><strong>Max user weight: </strong>300lbs<br /><strong>Motor: </strong>4.5 HP <br /><strong>Max speed:</strong> 10 mph<br /><strong>Max incline: </strong>18%<br /><strong>Connectivity: </strong>Bluetooth</p></div></div><p>One of the biggest barriers to buying a home treadmill is space. The <a href="https://www.tomsguide.com/best-picks/best-treadmills">best treadmills</a> are not small, and finding room is tricky even if the machine folds down flat.</p><p>The Walking G5i treadmill doesn’t just fold down flat. It also folds in half, and ends up around the size of a large suitcase when it is in its folded position. It’s still heavy, but it’s much easier to maneuver and store when not in use than most treadmills.</p><p>Importantly, it’s also impressive when unfolded and actually in use. The top speed is low, especially given the high price, but the belt runs smoothly and the max incline setting is very high, so you can increase the intensity on your walks and runs.</p><p>It’s still a little underspecced for its price in my view, but the fully foldable design might make it worth the outlay for those short on space. If you have room, however, a treadmill like the <a href="https://www.tomsguide.com/wellness/running/urevo-cybermega-smart-treadmill-review">Urevo CyberMega</a> offers a higher top speed at a lower price.</p><h2 class="article-body__section" id="section-walkingpad-g5i-treadmill-review-price-and-availability"><span>WalkingPad G5i treadmill review: price and availability</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ZggFHJN6qNtrFgCz85Aey4" name="WalkingPad G5i Treadmill" alt="WalkingPad G5i Treadmill" src="https://cdn.mos.cms.futurecdn.net/ZggFHJN6qNtrFgCz85Aey4-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The WalkingPad G5i treadmill costs $1,899 in the U.S. and £1,899 in the U.K., though it’s currently reduced to £1,599 in the latter and I’d expect fairly regular sales on the machine.</p><p>It’s an expensive machine, especially as for that kind of money you’d normally be looking at a gym-standard treadmill with a higher top speed and a larger design with a bigger running belt. </p><p>With the WalkingPad G5i you’re actually paying a premium for the smart folding design and its high max incline compared to other trifold models like the WalkingPad X218.</p><h2 class="article-body__section" id="section-walkingpad-g5i-treadmill-review-design"><span>WalkingPad G5i treadmill review: design</span></h2><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/cshpMCgjF5Mn82U2hzoxx4-1920-80.jpg" alt="WalkingPad G5i Treadmill" /><figcaption><small role="credit">Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/M2pTNckbVeg2HFN7CAg4z4-1920-80.jpg" alt="WalkingPad G5i Treadmill" /><figcaption><small role="credit">Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/yicGCKGpAd5zH2xVwSmRH4-1920-80.jpg" alt="WalkingPad G5i Treadmill" /><figcaption><small role="credit">Future</small></figcaption></figure></figure><p>The WalkingPad G5i arrives fully assembled, so you just need to open the box and unfold it to get started.</p><p>Folding the machine is simple to do using the foot lever, and once it’s fully assembled it feels remarkably sturdy — it didn’t feel any different to me during use than a treadmill that doesn’t fold in the middle of the belt.</p><p>When folded, it’s easier to lift and move around than treadmills that only fold flat or don’t fold at all, and you can stand it against a wall to save space, or slip it under a table.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="JMeMWyS7wGqEUwHSkDdQx4" name="WalkingPad G5i Treadmill" alt="WalkingPad G5i Treadmill" src="https://cdn.mos.cms.futurecdn.net/JMeMWyS7wGqEUwHSkDdQx4-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The console has touch-sensitive buttons you can use to change the incline, pick a preset workout program, and quickly adjust to speed to one of three preset options. </p><p>There’s also a dial in the center you use to start and stop the treadmill and adjust the speed, which is done in 0.1 increments with each turn, so it can take a while to get up to speed at the start of a run.</p><p>On the top of the console is a phone or tablet holder that looks small, but was very effective in holding my iPad during runs. I worried that it would shake off, but it stayed firmly in place even when using the machine at high speed or incline settings.</p><h2 class="article-body__section" id="section-walkingpad-g5i-treadmill-review-performance"><span>WalkingPad G5i treadmill review: performance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="8DZVATXf3MH3jcv8fvyry4" name="WalkingPad G5i Treadmill" alt="WalkingPad G5i Treadmill" src="https://cdn.mos.cms.futurecdn.net/8DZVATXf3MH3jcv8fvyry4-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>I ran once or twice a week on the WalkingPad G5i treadmill over several weeks of marathon training.</p><p>The top speed of 10mph is not fast enough for my workouts and for the price I’d expect a top speed of 12-12.5mph, which you’ll find on other treadmills for less, but it’s still a reasonable top speed for a foldable machine.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="sENvst7pmCYanBAq4eyuc4" name="WalkingPad G5i Treadmill" alt="WalkingPad G5i Treadmill" src="https://cdn.mos.cms.futurecdn.net/sENvst7pmCYanBAq4eyuc4-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>I found that the WalkingPad G5i did run smoothly for long periods at its max speed as well. It feels sturdier than most folding models in this regard, and the belt is surprisingly spacious for a folding treadmill.</p><p>However, if I tried to change the incline when running at high speeds things did get shaky. Once the incline is set, the shaking settles down, but it takes a very long time for the machine to change the incline, which rises/lowers by one level at a time using the buttons on the console.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="BMcah8oDoo2docq6rJq4z4" name="WalkingPad G5i Treadmill" alt="WalkingPad G5i Treadmill" src="https://cdn.mos.cms.futurecdn.net/BMcah8oDoo2docq6rJq4z4-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>If you’re walking on the machine while changing the incline the shaking isn’t so noticeable, and very few people are going to be running on the WalkingPad G5i once it gets anywhere near its 18% max incline, because that is very steep indeed.</p><p>There are preset workouts you can pick using the P button on the console before you start, which are explained/previewed in the user manual, but it’s more convenient to set these workouts up and follow them using the partner KS Fit app.</p><h2 class="article-body__section" id="section-walkingpad-g5i-treadmill-review-app"><span>WalkingPad G5i treadmill review: app</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kM9yc2dpBDRx93u5toMKz3" name="WalkingPad G5i Treadmill" alt="WalkingPad G5i Treadmill" src="https://cdn.mos.cms.futurecdn.net/kM9yc2dpBDRx93u5toMKz3-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The partner app for the WalkingPad G5i is the KS Fit app, not the WalkingPad+ app, which I found constantly crashed and wouldn’t connect to the treadmill.</p><p>With the KS Fit app installed, things were much smoother. The app connects easily to the treadmill and maintains that connection, and you can use it to follow guided workouts and adjust the settings on the WalkingPad G5i during activities.</p><p>The app does stay in portrait mode even on an iPad though, which means the stats and info on show is a bit cramped.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="srXqwhzpYVxuohGvi7zi54" name="WalkingPad G5i Treadmill" alt="WalkingPad G5i Treadmill" src="https://cdn.mos.cms.futurecdn.net/srXqwhzpYVxuohGvi7zi54-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>There are a lot of walking and running workouts in the app, but even though a ‘coach’ does appear on screen to run with you during them, they’re not an instructor and don’t speak to guide or motivate you in the session.</p><p>It’s not as helpful or engaging as the fully guided classes with instructors you get with Peloton or Echelon, but the sessions are a good option if you just need a bit of variety or prompting in what to do in your workouts.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="8JE8tCkQkYBhonvBgzFqu3" name="WalkingPad G5i Treadmill" alt="WalkingPad G5i Treadmill" src="https://cdn.mos.cms.futurecdn.net/8JE8tCkQkYBhonvBgzFqu3-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>During testing I also tried to link the WalkingPad G5i with other apps like Zwift, but the connection never held. Fortunately I can link to Zwift on my <a href="https://www.tomsguide.com/wellness/smartwatches/coros-pace-4-pro-review">Coros Pace 4 Pro </a>running watch and use that to match my speed to the treadmill.</p><h2 class="article-body__section" id="section-should-you-buy-the-walkingpad-g5i-treadmill"><span>Should you buy the WalkingPad G5i treadmill?</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:2419px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="rWpAf4XXyaABTjvrtanqtk" name="WalkingPad G5i Treadmill" alt="WalkingPad G5i Treadmill" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:0,l:0,cw:2419,ch:1361,q:80/rWpAf4XXyaABTjvrtanqtk.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The WalkingPad G5i offers something special in combining its tri-fold design with a very high max incline setting, which makes it great for people short on space who love doing intense walking workouts in particular.</p><p>It’s also a capable option for runners, though if you’re not worried about incline then the X Series models from WalkingPad offer the tri-fold design and higher max speeds at a lower price.</p><p>If you have room for a machine that only folds flat, the <a href="https://www.tomsguide.com/wellness/running/urevo-cybermega-smart-treadmill-review">Urevo CyberMega</a> impressed me in testing with its high top speed and powerful motor, and it costs $999.</p><p>I’d also consider looking at a <a href="https://www.tomsguide.com/wellness/fitness/peloton-finally-releases-a-treadmill-that-i-can-sorta-afford-and-it-sorta-folds-too">Peloton</a> or Echelon treadmill instead if you prefer to do instructor-led classes — the <a href="https://www.tomsguide.com/wellness/running/this-folding-treadmill-is-a-space-saving-peloton-alternative-thats-only-worth-buying-if-youre-happy-to-pay-a-subscription">Echelon Stride-6s-10</a> is a good folding option, though more expensive than the WalkingPad G5i and you’ll also have to pay for a monthly subscription to unlock the classes.</p><p>The WalkingPad G5i did impress me in testing overall, but there are some better value alternatives out there if you don’t need its tri-fold/high incline combo.</p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/running/walkingpad-g5i-treadmill-review</link>
                                                                            <description>
                            <![CDATA[ The WalkingPad G5i treadmill might be the perfect home training option if you don’t have much space, but it’s underspecced for its high price. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">5bN8fBmfKqPja25gAQMxSH</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/zpkU92rBxhwLysHzUECFcP-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 23 Oct 2026 10:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Running]]></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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/zpkU92rBxhwLysHzUECFcP-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[WalkingPad G5i Treadmill]]></media:description>                                                            <media:text><![CDATA[WalkingPad G5i Treadmill]]></media:text>
                                <media:title type="plain"><![CDATA[WalkingPad G5i Treadmill]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/zpkU92rBxhwLysHzUECFcP-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <div  class="fancy-box"><div class="fancy_box-title">WalkindPad G5i Specs</div><div class="fancy_box_body"><p class="fancy-box__body-text"><strong>Dimensions (unfolded): </strong>64.6 x 33.4 x 43.4 inches<br /><strong>Dimensions (folded)</strong>: 45.7 x 33.4 x 10.2 inches<br /><strong>Running surface: </strong>51.2 x 19.7 inches<br /><strong>Weight: </strong>150lbs<br /><strong>Max user weight: </strong>300lbs<br /><strong>Motor: </strong>4.5 HP <br /><strong>Max speed:</strong> 10 mph<br /><strong>Max incline: </strong>18%<br /><strong>Connectivity: </strong>Bluetooth</p></div></div><p>One of the biggest barriers to buying a home treadmill is space. The <a href="https://www.tomsguide.com/best-picks/best-treadmills">best treadmills</a> are not small, and finding room is tricky even if the machine folds down flat.</p><p>The Walking G5i treadmill doesn’t just fold down flat. It also folds in half, and ends up around the size of a large suitcase when it is in its folded position. It’s still heavy, but it’s much easier to maneuver and store when not in use than most treadmills.</p><p>Importantly, it’s also impressive when unfolded and actually in use. The top speed is low, especially given the high price, but the belt runs smoothly and the max incline setting is very high, so you can increase the intensity on your walks and runs.</p><p>It’s still a little underspecced for its price in my view, but the fully foldable design might make it worth the outlay for those short on space. If you have room, however, a treadmill like the <a href="https://www.tomsguide.com/wellness/running/urevo-cybermega-smart-treadmill-review">Urevo CyberMega</a> offers a higher top speed at a lower price.</p><h2 class="article-body__section" id="section-walkingpad-g5i-treadmill-review-price-and-availability"><span>WalkingPad G5i treadmill review: price and availability</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ZggFHJN6qNtrFgCz85Aey4" name="WalkingPad G5i Treadmill" alt="WalkingPad G5i Treadmill" src="https://cdn.mos.cms.futurecdn.net/ZggFHJN6qNtrFgCz85Aey4-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The WalkingPad G5i treadmill costs $1,899 in the U.S. and £1,899 in the U.K., though it’s currently reduced to £1,599 in the latter and I’d expect fairly regular sales on the machine.</p><p>It’s an expensive machine, especially as for that kind of money you’d normally be looking at a gym-standard treadmill with a higher top speed and a larger design with a bigger running belt. </p><p>With the WalkingPad G5i you’re actually paying a premium for the smart folding design and its high max incline compared to other trifold models like the WalkingPad X218.</p><h2 class="article-body__section" id="section-walkingpad-g5i-treadmill-review-design"><span>WalkingPad G5i treadmill review: design</span></h2><figure role="gallery"><figure><img src="https://cdn.mos.cms.futurecdn.net/cshpMCgjF5Mn82U2hzoxx4-1920-80.jpg" alt="WalkingPad G5i Treadmill" /><figcaption><small role="credit">Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/M2pTNckbVeg2HFN7CAg4z4-1920-80.jpg" alt="WalkingPad G5i Treadmill" /><figcaption><small role="credit">Future</small></figcaption></figure><figure><img src="https://cdn.mos.cms.futurecdn.net/yicGCKGpAd5zH2xVwSmRH4-1920-80.jpg" alt="WalkingPad G5i Treadmill" /><figcaption><small role="credit">Future</small></figcaption></figure></figure><p>The WalkingPad G5i arrives fully assembled, so you just need to open the box and unfold it to get started.</p><p>Folding the machine is simple to do using the foot lever, and once it’s fully assembled it feels remarkably sturdy — it didn’t feel any different to me during use than a treadmill that doesn’t fold in the middle of the belt.</p><p>When folded, it’s easier to lift and move around than treadmills that only fold flat or don’t fold at all, and you can stand it against a wall to save space, or slip it under a table.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="JMeMWyS7wGqEUwHSkDdQx4" name="WalkingPad G5i Treadmill" alt="WalkingPad G5i Treadmill" src="https://cdn.mos.cms.futurecdn.net/JMeMWyS7wGqEUwHSkDdQx4-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The console has touch-sensitive buttons you can use to change the incline, pick a preset workout program, and quickly adjust to speed to one of three preset options. </p><p>There’s also a dial in the center you use to start and stop the treadmill and adjust the speed, which is done in 0.1 increments with each turn, so it can take a while to get up to speed at the start of a run.</p><p>On the top of the console is a phone or tablet holder that looks small, but was very effective in holding my iPad during runs. I worried that it would shake off, but it stayed firmly in place even when using the machine at high speed or incline settings.</p><h2 class="article-body__section" id="section-walkingpad-g5i-treadmill-review-performance"><span>WalkingPad G5i treadmill review: performance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="8DZVATXf3MH3jcv8fvyry4" name="WalkingPad G5i Treadmill" alt="WalkingPad G5i Treadmill" src="https://cdn.mos.cms.futurecdn.net/8DZVATXf3MH3jcv8fvyry4-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>I ran once or twice a week on the WalkingPad G5i treadmill over several weeks of marathon training.</p><p>The top speed of 10mph is not fast enough for my workouts and for the price I’d expect a top speed of 12-12.5mph, which you’ll find on other treadmills for less, but it’s still a reasonable top speed for a foldable machine.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="sENvst7pmCYanBAq4eyuc4" name="WalkingPad G5i Treadmill" alt="WalkingPad G5i Treadmill" src="https://cdn.mos.cms.futurecdn.net/sENvst7pmCYanBAq4eyuc4-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>I found that the WalkingPad G5i did run smoothly for long periods at its max speed as well. It feels sturdier than most folding models in this regard, and the belt is surprisingly spacious for a folding treadmill.</p><p>However, if I tried to change the incline when running at high speeds things did get shaky. Once the incline is set, the shaking settles down, but it takes a very long time for the machine to change the incline, which rises/lowers by one level at a time using the buttons on the console.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="BMcah8oDoo2docq6rJq4z4" name="WalkingPad G5i Treadmill" alt="WalkingPad G5i Treadmill" src="https://cdn.mos.cms.futurecdn.net/BMcah8oDoo2docq6rJq4z4-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>If you’re walking on the machine while changing the incline the shaking isn’t so noticeable, and very few people are going to be running on the WalkingPad G5i once it gets anywhere near its 18% max incline, because that is very steep indeed.</p><p>There are preset workouts you can pick using the P button on the console before you start, which are explained/previewed in the user manual, but it’s more convenient to set these workouts up and follow them using the partner KS Fit app.</p><h2 class="article-body__section" id="section-walkingpad-g5i-treadmill-review-app"><span>WalkingPad G5i treadmill review: app</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="kM9yc2dpBDRx93u5toMKz3" name="WalkingPad G5i Treadmill" alt="WalkingPad G5i Treadmill" src="https://cdn.mos.cms.futurecdn.net/kM9yc2dpBDRx93u5toMKz3-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The partner app for the WalkingPad G5i is the KS Fit app, not the WalkingPad+ app, which I found constantly crashed and wouldn’t connect to the treadmill.</p><p>With the KS Fit app installed, things were much smoother. The app connects easily to the treadmill and maintains that connection, and you can use it to follow guided workouts and adjust the settings on the WalkingPad G5i during activities.</p><p>The app does stay in portrait mode even on an iPad though, which means the stats and info on show is a bit cramped.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="srXqwhzpYVxuohGvi7zi54" name="WalkingPad G5i Treadmill" alt="WalkingPad G5i Treadmill" src="https://cdn.mos.cms.futurecdn.net/srXqwhzpYVxuohGvi7zi54-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>There are a lot of walking and running workouts in the app, but even though a ‘coach’ does appear on screen to run with you during them, they’re not an instructor and don’t speak to guide or motivate you in the session.</p><p>It’s not as helpful or engaging as the fully guided classes with instructors you get with Peloton or Echelon, but the sessions are a good option if you just need a bit of variety or prompting in what to do in your workouts.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="8JE8tCkQkYBhonvBgzFqu3" name="WalkingPad G5i Treadmill" alt="WalkingPad G5i Treadmill" src="https://cdn.mos.cms.futurecdn.net/8JE8tCkQkYBhonvBgzFqu3-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>During testing I also tried to link the WalkingPad G5i with other apps like Zwift, but the connection never held. Fortunately I can link to Zwift on my <a href="https://www.tomsguide.com/wellness/smartwatches/coros-pace-4-pro-review">Coros Pace 4 Pro </a>running watch and use that to match my speed to the treadmill.</p><h2 class="article-body__section" id="section-should-you-buy-the-walkingpad-g5i-treadmill"><span>Should you buy the WalkingPad G5i treadmill?</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:2419px;"><p class="vanilla-image-block" style="padding-top:56.26%;"><img id="rWpAf4XXyaABTjvrtanqtk" name="WalkingPad G5i Treadmill" alt="WalkingPad G5i Treadmill" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:0,l:0,cw:2419,ch:1361,q:80/rWpAf4XXyaABTjvrtanqtk.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The WalkingPad G5i offers something special in combining its tri-fold design with a very high max incline setting, which makes it great for people short on space who love doing intense walking workouts in particular.</p><p>It’s also a capable option for runners, though if you’re not worried about incline then the X Series models from WalkingPad offer the tri-fold design and higher max speeds at a lower price.</p><p>If you have room for a machine that only folds flat, the <a href="https://www.tomsguide.com/wellness/running/urevo-cybermega-smart-treadmill-review">Urevo CyberMega</a> impressed me in testing with its high top speed and powerful motor, and it costs $999.</p><p>I’d also consider looking at a <a href="https://www.tomsguide.com/wellness/fitness/peloton-finally-releases-a-treadmill-that-i-can-sorta-afford-and-it-sorta-folds-too">Peloton</a> or Echelon treadmill instead if you prefer to do instructor-led classes — the <a href="https://www.tomsguide.com/wellness/running/this-folding-treadmill-is-a-space-saving-peloton-alternative-thats-only-worth-buying-if-youre-happy-to-pay-a-subscription">Echelon Stride-6s-10</a> is a good folding option, though more expensive than the WalkingPad G5i and you’ll also have to pay for a monthly subscription to unlock the classes.</p><p>The WalkingPad G5i did impress me in testing overall, but there are some better value alternatives out there if you don’t need its tri-fold/high incline combo.</p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Forget heavy squats — a physical therapist shares 5 joint-friendly moves to build leg power after 60 ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Squats are one of the most functional exercises, and doing them regularly as you age helps you preserve strength, muscle and power for activities like climbing stairs or going to the bathroom unaided; in short, strong legs keep you independent. </p><p>But not everyone can do squats, whether that's due to mobility, injury, health conditions, or preference. So, I turned to physical therapist Leighton Roberts, managing director at <a href="https://www.grosvenormobility.co.uk/" target="_blank" rel="nofollow">Grosvenor Mobility,</a> for some advice. </p><p>“Here are five simple exercises I'd recommend trying, provided they're suitable for your individual health and mobility needs," says Roberts. Read on for the moves and how to do them.</p><h2 id="5-lower-body-exercises-from-a-physical-therapist-to-build-leg-strength-and-power">5 lower-body exercises from a physical therapist to build leg strength and power</h2><p>"Maintaining joint strength is essential for staying active, mobile and independent," Roberts tells us. "For those experiencing joint stiffness or reduced mobility, gentle bed exercises are a great starting point. They help strengthen the muscles surrounding your hips without needing specialist gym equipment. An adjustable bed can also offer additional comfort when positioning yourself before and after exercise."</p><p>It's up to you where you perform these exercises, of course, whether that's on a bed or using an exercise mat rolled out at home. </p><h3 class="article-body__section" id="section-1-straight-leg-raises"><span> 1. Straight leg raises</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="FJKaaGt82LyvQUFc9zo7Ni" name="leg lifts.jpg" alt="a woman doing leg lifts" src="https://cdn.mos.cms.futurecdn.net/FJKaaGt82LyvQUFc9zo7Ni-1920-80.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/lioputra)</span></figcaption></figure><p>"These target the hip flexor muscles, helping with everyday movements such as walking, climbing stairs and lifting your legs," says Roberts.</p><ul><li>Lie on your back with your legs extended and arms by your sides</li><li>Engage your core and lightly tuck your pelvis toward you</li><li>Lift your legs into the air, keeping a soft bend in your knees</li><li>With control, lower your legs toward the floor. Only lower them as far as you can control without your back arching away from the mat</li><li><strong>Continue for 6-10 reps and 2 sets.</strong></li></ul><h3 class="article-body__section" id="section-2-hip-bridges"><span>2. Hip bridges</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="9J9AEAPFpcKYtHswZPkhAd" name="glute bridge.jpg" alt="a photo of a man doing a glute bridge" src="https://cdn.mos.cms.futurecdn.net/9J9AEAPFpcKYtHswZPkhAd-1920-80.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>"Hip bridges strengthen the gluteal muscles, improving hip stability and supporting movements such as standing up and walking."</p><ul><li>Lie on your back with your feet hip-width apart and knees bent</li><li>Press through your heels and lift your hips into the air</li><li>Squeeze your glutes at the top and pause</li><li>Slowly lower through your spine to reset</li><li><strong>Continue for 6-10 reps and 2 sets.</strong></li></ul><h3 class="article-body__section" id="section-3-side-lying-leg-raises"><span>3. Side-lying leg raises</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="eZ5tyxx62YdB7rhgJsErYb" name="side leg lift" alt="an illo of a man doing a side leg lift" src="https://cdn.mos.cms.futurecdn.net/eZ5tyxx62YdB7rhgJsErYb-1920-80.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>"These strengthen the outer hip muscles, which help stabilize your pelvis and maintain balance when walking."</p><ul><li>Lie on your side with your elbow resting and legs extended</li><li>With control, lift your top leg into the air and squeeze your glutes at the top. Your hips should stay facing forward</li><li>Lower your leg and repeat. Switch sides</li><li><strong>Continue for 6-10 reps and 2 sets.</strong></li></ul><h3 class="article-body__section" id="section-4-heel-slides"><span>4. Heel slides </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:1510px;"><p class="vanilla-image-block" style="padding-top:56.29%;"><img id="FauBQDPaVo2GGhUSmgKfj4" name="heel slides blue" alt="an illo of a woman doing heel slide exercise" src="https://cdn.mos.cms.futurecdn.net/FauBQDPaVo2GGhUSmgKfj4-1920-80.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: Shutterstock)</span></figcaption></figure><p>"Heel slides encourage gentle movement through the hip and knee joints, helping improve flexibility and relieve stiffness after periods of inactivity."</p><ul><li>Lie on your back with your legs extended</li><li>Slowly bend one knee and slide your heel toward your butt</li><li>Hold for a few seconds, then slowly slide your foot away to extend the leg again</li><li><strong>Continue for 6-10 reps and 2 sets per side.</strong></li></ul><h3 class="article-body__section" id="section-5-clamshells"><span>5. Clamshells</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="wp9e4bnKz7ZcrwvM2sdDE5" name="clamshells illo.jpg" alt="an illo of a woman doing clamshells with a resistance band" src="https://cdn.mos.cms.futurecdn.net/wp9e4bnKz7ZcrwvM2sdDE5-1920-80.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>"Clamshells target the muscles around the outer hips, helping improve stability, balance and control during everyday movements."</p><ul><li>Lie on your side with your hips, thighs and ankles stacked at 90 degrees</li><li>Keep the inner sides of your feet pressed together, then slowly open your top knee and squeeze your outer glutes as you open your hips. Keep your hips facing forward</li><li>Pause, then lower your knee with control</li><li><strong>Continue for 6-10 reps and 2 sets per side.</strong></li></ul><p>Start with these exercises two to three times a week, alongside other activities such as walking, running, lifting weights, or gardening. Overall, consistency is one of the most important factors in maintaining strength and long-term mobility.</p><p>While these exercises are recommended by a qualified physical therapist, you should always listen to your body and stop if you feel sharp pain, numbness, or tingling. Working with a physical therapist, physician, or similar professional will help you determine the issue and provide specialized recommendations based on your personal journey.</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-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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/i-teach-people-how-to-be-strong-and-mobile-this-is-the-one-exercise-i-regret-ignoring-for-years" target="_blank">I teach people how to be strong and mobile: this is the one exercise I regret ignoring for years</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> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/workouts/forget-heavy-squats-a-physical-therapist-shares-5-joint-friendly-moves-to-build-leg-power-after-60</link>
                                                                            <description>
                            <![CDATA[ A physical therapist recommends five crucial strengthening exercises for leg power in people over 60, none of which are squats. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">5KumXJ6THzwbZfgnnTFcsb</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/rFmDncitwtNguzdZG8npiK-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 23 Oct 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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/rFmDncitwtNguzdZG8npiK-1920-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Male in shorts and t-shirt balancing on one leg while hugging his knee outdoors ]]></media:description>                                                            <media:text><![CDATA[Male in shorts and t-shirt balancing on one leg while hugging his knee outdoors ]]></media:text>
                                <media:title type="plain"><![CDATA[Male in shorts and t-shirt balancing on one leg while hugging his knee outdoors ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/rFmDncitwtNguzdZG8npiK-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Squats are one of the most functional exercises, and doing them regularly as you age helps you preserve strength, muscle and power for activities like climbing stairs or going to the bathroom unaided; in short, strong legs keep you independent. </p><p>But not everyone can do squats, whether that's due to mobility, injury, health conditions, or preference. So, I turned to physical therapist Leighton Roberts, managing director at <a href="https://www.grosvenormobility.co.uk/" target="_blank" rel="nofollow">Grosvenor Mobility,</a> for some advice. </p><p>“Here are five simple exercises I'd recommend trying, provided they're suitable for your individual health and mobility needs," says Roberts. Read on for the moves and how to do them.</p><h2 id="5-lower-body-exercises-from-a-physical-therapist-to-build-leg-strength-and-power">5 lower-body exercises from a physical therapist to build leg strength and power</h2><p>"Maintaining joint strength is essential for staying active, mobile and independent," Roberts tells us. "For those experiencing joint stiffness or reduced mobility, gentle bed exercises are a great starting point. They help strengthen the muscles surrounding your hips without needing specialist gym equipment. An adjustable bed can also offer additional comfort when positioning yourself before and after exercise."</p><p>It's up to you where you perform these exercises, of course, whether that's on a bed or using an exercise mat rolled out at home. </p><h3 class="article-body__section" id="section-1-straight-leg-raises"><span> 1. Straight leg raises</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="FJKaaGt82LyvQUFc9zo7Ni" name="leg lifts.jpg" alt="a woman doing leg lifts" src="https://cdn.mos.cms.futurecdn.net/FJKaaGt82LyvQUFc9zo7Ni-1920-80.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/lioputra)</span></figcaption></figure><p>"These target the hip flexor muscles, helping with everyday movements such as walking, climbing stairs and lifting your legs," says Roberts.</p><ul><li>Lie on your back with your legs extended and arms by your sides</li><li>Engage your core and lightly tuck your pelvis toward you</li><li>Lift your legs into the air, keeping a soft bend in your knees</li><li>With control, lower your legs toward the floor. Only lower them as far as you can control without your back arching away from the mat</li><li><strong>Continue for 6-10 reps and 2 sets.</strong></li></ul><h3 class="article-body__section" id="section-2-hip-bridges"><span>2. Hip bridges</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="9J9AEAPFpcKYtHswZPkhAd" name="glute bridge.jpg" alt="a photo of a man doing a glute bridge" src="https://cdn.mos.cms.futurecdn.net/9J9AEAPFpcKYtHswZPkhAd-1920-80.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>"Hip bridges strengthen the gluteal muscles, improving hip stability and supporting movements such as standing up and walking."</p><ul><li>Lie on your back with your feet hip-width apart and knees bent</li><li>Press through your heels and lift your hips into the air</li><li>Squeeze your glutes at the top and pause</li><li>Slowly lower through your spine to reset</li><li><strong>Continue for 6-10 reps and 2 sets.</strong></li></ul><h3 class="article-body__section" id="section-3-side-lying-leg-raises"><span>3. Side-lying leg raises</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="eZ5tyxx62YdB7rhgJsErYb" name="side leg lift" alt="an illo of a man doing a side leg lift" src="https://cdn.mos.cms.futurecdn.net/eZ5tyxx62YdB7rhgJsErYb-1920-80.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>"These strengthen the outer hip muscles, which help stabilize your pelvis and maintain balance when walking."</p><ul><li>Lie on your side with your elbow resting and legs extended</li><li>With control, lift your top leg into the air and squeeze your glutes at the top. Your hips should stay facing forward</li><li>Lower your leg and repeat. Switch sides</li><li><strong>Continue for 6-10 reps and 2 sets.</strong></li></ul><h3 class="article-body__section" id="section-4-heel-slides"><span>4. Heel slides </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:1510px;"><p class="vanilla-image-block" style="padding-top:56.29%;"><img id="FauBQDPaVo2GGhUSmgKfj4" name="heel slides blue" alt="an illo of a woman doing heel slide exercise" src="https://cdn.mos.cms.futurecdn.net/FauBQDPaVo2GGhUSmgKfj4-1920-80.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: Shutterstock)</span></figcaption></figure><p>"Heel slides encourage gentle movement through the hip and knee joints, helping improve flexibility and relieve stiffness after periods of inactivity."</p><ul><li>Lie on your back with your legs extended</li><li>Slowly bend one knee and slide your heel toward your butt</li><li>Hold for a few seconds, then slowly slide your foot away to extend the leg again</li><li><strong>Continue for 6-10 reps and 2 sets per side.</strong></li></ul><h3 class="article-body__section" id="section-5-clamshells"><span>5. Clamshells</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="wp9e4bnKz7ZcrwvM2sdDE5" name="clamshells illo.jpg" alt="an illo of a woman doing clamshells with a resistance band" src="https://cdn.mos.cms.futurecdn.net/wp9e4bnKz7ZcrwvM2sdDE5-1920-80.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>"Clamshells target the muscles around the outer hips, helping improve stability, balance and control during everyday movements."</p><ul><li>Lie on your side with your hips, thighs and ankles stacked at 90 degrees</li><li>Keep the inner sides of your feet pressed together, then slowly open your top knee and squeeze your outer glutes as you open your hips. Keep your hips facing forward</li><li>Pause, then lower your knee with control</li><li><strong>Continue for 6-10 reps and 2 sets per side.</strong></li></ul><p>Start with these exercises two to three times a week, alongside other activities such as walking, running, lifting weights, or gardening. Overall, consistency is one of the most important factors in maintaining strength and long-term mobility.</p><p>While these exercises are recommended by a qualified physical therapist, you should always listen to your body and stop if you feel sharp pain, numbness, or tingling. Working with a physical therapist, physician, or similar professional will help you determine the issue and provide specialized recommendations based on your personal journey.</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-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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/i-teach-people-how-to-be-strong-and-mobile-this-is-the-one-exercise-i-regret-ignoring-for-years" target="_blank">I teach people how to be strong and mobile: this is the one exercise I regret ignoring for years</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[ REI is taking up to 50% off best-selling Arc’teryx gear for fall — here are my 13 favorite deals ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Arc'teryx is commonly known for its winter gear, but many of its best-selling pieces are also great for fall. From lightweight layers to hiking pants and rain jackets, they have plenty of high-quality styles built for the changing seasons ahead. </p><p>Case in point: <a href="https://www.rei.com/b/arcteryx/f/scd-deals?" target="_blank" rel="nofollow">REI is currently knocking up to 50% off best-selling Arc'teryx apparel for fall</a>. Whether you’re planning alpine hikes, backcountry trail rides or you simply want to spend more time in the great outdoors, the Arc'teryx sale is the perfect opportunity to invest in top-tier gear for all your upcoming adventures. </p><p>So don't wait! Keep scrolling to check out the rest of my favorite finds from the Arc'teryx sale at REI.  </p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><a href="https://www.rei.com/b/arcteryx/f/scd-deals" target="_blank" rel="nofollow"><strong>shop all Arc'teryx deals at REI</strong></a></li><li><strong>Arc'teryx Taema Tank Top (Women's): </strong><a href="https://www.rei.com/product/C05677/arcteryx-taema-tank-top-womens" target="_blank" rel="nofollow"><strong>was $60 now $38</strong></a></li><li><strong>Arc'teryx Cormac Logo T-Shirt (Men's): </strong><a href="https://www.rei.com/product/C01312/arcteryx-cormac-logo-t-shirt-mens" target="_blank" rel="nofollow"><strong>was $80 now $39</strong></a></li><li><strong>Arc'teryx Cormac Crew Long-Sleeve Shirt (Men's): </strong><a href="https://www.rei.com/product/218811/arcteryx-cormac-crew-long-sleeve-shirt-mens?" target="_blank" rel="nofollow"><strong>was $80 now $55</strong></a></li><li><strong>Arc'teryx Satoro Merino Wool Long-Sleeve Top (Women's): </strong><a href="https://www.rei.com/product/C11758/arcteryx-satoro-merino-wool-crew-neck-long-sleeve-base-layer-top-womens" target="_blank" rel="nofollow"><strong>was $120 now $95</strong></a></li><li><strong>Arc'teryx Atom Insulated Hoody (Men's): </strong><a href="https://www.rei.com/product/243175/arcteryx-atom-insulated-hoody-mens?" target="_blank" rel="nofollow"><strong>was $300 now $199</strong></a></li><li><strong>Arc'teryx Beta SL Jacket (Men's): </strong><a href="https://www.rei.com/product/235112/arcteryx-beta-sl-jacket-mens" target="_blank" rel="nofollow"><strong>was $500 now $299</strong></a></li></ul><h3 class="article-body__section" id="section-arc-teryx-deals"><span>Arc'teryx Deals </span></h3><div class="product"><a data-dimension112="7069a3a4-ce3a-11f1-b31e-2f77c6693aab" data-action="Deal Block" data-label="Taema Tank Top (Women's)" data-dimension48="Taema Tank Top (Women's)" data-dimension25="$38" href="https://www.rei.com/product/C05677/arcteryx-taema-tank-top-womens" 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="rXhnnkZbPZd2ntrTrKECK3" name="Taema tank top" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/rXhnnkZbPZd2ntrTrKECK3-1920-80.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C05677/arcteryx-taema-tank-top-womens" target="_blank" rel="nofollow" data-dimension112="7069a3a4-ce3a-11f1-b31e-2f77c6693aab" data-action="Deal Block" data-label="Taema Tank Top (Women's)" data-dimension48="Taema Tank Top (Women's)" data-dimension25="$38">Taema Tank Top (Women's): was $60 now $38</a></strong><br />This racerback, crew neck tank top features a breathable fabric that wicks moisture away and dries quickly, making it perfect for longer hikes. It's soft, comfortable and built for performance. <a class="view-deal button" href="https://www.rei.com/product/C05677/arcteryx-taema-tank-top-womens" target="_blank" rel="nofollow" data-dimension112="7069a3a4-ce3a-11f1-b31e-2f77c6693aab" data-action="Deal Block" data-label="Taema Tank Top (Women's)" data-dimension48="Taema Tank Top (Women's)" data-dimension25="$38">View Deal</a></p></div><div class="product"><a data-dimension112="7069a43a-ce3a-11f1-92c0-15ed0468cebd" data-action="Deal Block" data-label="Cormac Logo T-Shirt (Men's)" data-dimension48="Cormac Logo T-Shirt (Men's)" data-dimension25="$39" href="https://www.rei.com/product/C01312/arcteryx-cormac-logo-t-shirt-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="jJvHixb5ZKWc2ciLwkBt3J" name="Arc'teryx tee" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jJvHixb5ZKWc2ciLwkBt3J-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01312/arcteryx-cormac-logo-t-shirt-mens" target="_blank" rel="nofollow" data-dimension112="7069a43a-ce3a-11f1-92c0-15ed0468cebd" data-action="Deal Block" data-label="Cormac Logo T-Shirt (Men's)" data-dimension48="Cormac Logo T-Shirt (Men's)" data-dimension25="$39">Cormac Logo T-Shirt (Men's): was $80 now $39</a></strong><br />If you're a big Arc'teryx fan (who isn't?) then you'll want to grab this t-shirt. It has the Arc'teryx logo front and center and is made of comfortable, breathable cotton jersey fabric.<a class="view-deal button" href="https://www.rei.com/product/C01312/arcteryx-cormac-logo-t-shirt-mens" target="_blank" rel="nofollow" data-dimension112="7069a43a-ce3a-11f1-92c0-15ed0468cebd" data-action="Deal Block" data-label="Cormac Logo T-Shirt (Men's)" data-dimension48="Cormac Logo T-Shirt (Men's)" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="6afc31ba-cec2-11f1-b54e-012b3a9d2ab0" data-action="Deal Block" data-label="Small Bird Cap" data-dimension48="Small Bird Cap" data-dimension25="$39" href="https://www.rei.com/product/C11817/arcteryx-small-bird-cap" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="GhyZp7wzR7ogFWo5rp5cfZ" name="Arc'teryx hst" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/GhyZp7wzR7ogFWo5rp5cfZ-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C11817/arcteryx-small-bird-cap" target="_blank" rel="nofollow" data-dimension112="6afc31ba-cec2-11f1-b54e-012b3a9d2ab0" data-action="Deal Block" data-label="Small Bird Cap" data-dimension48="Small Bird Cap" data-dimension25="$39">Small Bird Cap: was $50 now $39</a></strong><br />Need a new hat for the trails? The Arc'teryx Small Bird hat is made with breathable, stretchy material and a soft, quick-drying headband that will keep your head feeling airy and dry. It will get the job done on the toughest of routes. <a class="view-deal button" href="https://www.rei.com/product/C11817/arcteryx-small-bird-cap" target="_blank" rel="nofollow" data-dimension112="6afc31ba-cec2-11f1-b54e-012b3a9d2ab0" data-action="Deal Block" data-label="Small Bird Cap" data-dimension48="Small Bird Cap" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="7069a4bc-ce3a-11f1-b123-35461167aea6" data-action="Deal Block" data-label="Word Toque (Unisex)" data-dimension48="Word Toque (Unisex)" data-dimension25="$44" href="https://www.rei.com/product/C11815/arcteryx-color-block-toque" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="KFMjo5N4Bne6DPzoJtjey5" name="Arc'teryx deals" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/KFMjo5N4Bne6DPzoJtjey5-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C11815/arcteryx-color-block-toque" target="_blank" rel="nofollow" data-dimension112="7069a4bc-ce3a-11f1-b123-35461167aea6" data-action="Deal Block" data-label="Word Toque (Unisex)" data-dimension48="Word Toque (Unisex)" data-dimension25="$44">Word Toque (Unisex): was $55 now $44</a></strong><br />A cozy, cuffed beanie never goes out of style, and with temperatures dropping, this blue staple is ready to keep you warm and fashionable, all fall and winter long.<a class="view-deal button" href="https://www.rei.com/product/C11815/arcteryx-color-block-toque" target="_blank" rel="nofollow" data-dimension112="7069a4bc-ce3a-11f1-b123-35461167aea6" data-action="Deal Block" data-label="Word Toque (Unisex)" data-dimension48="Word Toque (Unisex)" data-dimension25="$44">View Deal</a></p></div><div class="product"><a data-dimension112="6afc323c-cec2-11f1-b339-7141bbc60ef7" data-action="Deal Block" data-label="Base Layer Bottoms (Women's)" data-dimension48="Base Layer Bottoms (Women's)" data-dimension25="$49" href="https://www.rei.com/product/209252/arcteryx-rho-base-layer-bottoms-womens?color=BLACK" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:588px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="rn5oNYv8T4jW6o67MGfR9B" name="Rho Base Layer" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/rn5oNYv8T4jW6o67MGfR9B-1920-80.jpg" mos="" align="middle" fullscreen="" width="588" height="588" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/209252/arcteryx-rho-base-layer-bottoms-womens?color=BLACK" target="_blank" rel="nofollow" data-dimension112="6afc323c-cec2-11f1-b339-7141bbc60ef7" data-action="Deal Block" data-label="Base Layer Bottoms (Women's)" data-dimension48="Base Layer Bottoms (Women's)" data-dimension25="$49">Base Layer Bottoms (Women's): was $100 now $49</a></strong><br />These heavyweight bottoms from Arc’teryx just got a massive discount. Arc’teryx’s Polygiene treatment helps with odor, while the Torrent brushed fleece is soft against your skin. <a class="view-deal button" href="https://www.rei.com/product/209252/arcteryx-rho-base-layer-bottoms-womens?color=BLACK" target="_blank" rel="nofollow" data-dimension112="6afc323c-cec2-11f1-b339-7141bbc60ef7" data-action="Deal Block" data-label="Base Layer Bottoms (Women's)" data-dimension48="Base Layer Bottoms (Women's)" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="7069a52a-ce3a-11f1-a050-ed45b7697e73" data-action="Deal Block" data-label="Cormac Crew Long-Sleeve Shirt (Men's)" data-dimension48="Cormac Crew Long-Sleeve Shirt (Men's)" data-dimension25="$55" href="https://www.rei.com/product/218811/arcteryx-cormac-crew-long-sleeve-shirt-mens?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1450px;"><p class="vanilla-image-block" style="padding-top:103.45%;"><img id="9ovahzghZXKKQwERkhLbWH" name="cormac" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/9ovahzghZXKKQwERkhLbWH-1920-80.jpg" mos="" align="middle" fullscreen="" width="1450" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/218811/arcteryx-cormac-crew-long-sleeve-shirt-mens?" target="_blank" rel="nofollow" data-dimension112="7069a52a-ce3a-11f1-a050-ed45b7697e73" data-action="Deal Block" data-label="Cormac Crew Long-Sleeve Shirt (Men's)" data-dimension48="Cormac Crew Long-Sleeve Shirt (Men's)" data-dimension25="$55">Cormac Crew Long-Sleeve Shirt (Men's): was $80 now $55</a></strong><br />This long-sleeved exercise top was inspired by running apparel, but then adapted to make it suitable for mountain-based high-intensity activities. It's breathable, maximizes airflow, and is designed to reduce chafing. <a class="view-deal button" href="https://www.rei.com/product/218811/arcteryx-cormac-crew-long-sleeve-shirt-mens?" target="_blank" rel="nofollow" data-dimension112="7069a52a-ce3a-11f1-a050-ed45b7697e73" data-action="Deal Block" data-label="Cormac Crew Long-Sleeve Shirt (Men's)" data-dimension48="Cormac Crew Long-Sleeve Shirt (Men's)" data-dimension25="$55">View Deal</a></p></div><div class="product"><a data-dimension112="7069a598-ce3a-11f1-9ea6-fde28fa3d81e" data-action="Deal Block" data-label="Cranbrook Hat" data-dimension48="Cranbrook Hat" data-dimension25="$68" href="https://www.rei.com/product/246886/arcteryx-cranbrook-hat" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:588px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="x8NaJfMivLbsqngaKxLaKZ" name="Arc'teryx bucket hat" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/x8NaJfMivLbsqngaKxLaKZ-1920-80.jpg" mos="" align="middle" fullscreen="" width="588" height="588" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>If you have some backcountry adventures planned, this is the hat you'll want to bring along. The Arc'teryx Cranbrook hat has a wide brim that shades your face, ears and neck from the sun, and it's ventilated to keep you nice and cool. <a class="view-deal button" href="https://www.rei.com/product/246886/arcteryx-cranbrook-hat" target="_blank" rel="nofollow" data-dimension112="7069a598-ce3a-11f1-9ea6-fde28fa3d81e" data-action="Deal Block" data-label="Cranbrook Hat" data-dimension48="Cranbrook Hat" data-dimension25="$68">View Deal</a></p></div><div class="product"><a data-dimension112="7069a610-ce3a-11f1-92f0-c50a0fcc37f6" data-action="Deal Block" data-label="Incendo Pants (Men's)" data-dimension48="Incendo Pants (Men's)" data-dimension25="$90" href="https://www.rei.com/product/229268/arcteryx-incendo-pants-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="KfdPeGj43M8ocSgpPLLmjZ" name="incendo" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/KfdPeGj43M8ocSgpPLLmjZ-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/229268/arcteryx-incendo-pants-mens" target="_blank" rel="nofollow" data-dimension112="7069a610-ce3a-11f1-92f0-c50a0fcc37f6" data-action="Deal Block" data-label="Incendo Pants (Men's)" data-dimension48="Incendo Pants (Men's)" data-dimension25="$90">Incendo Pants (Men's): was $130 now $90</a></strong><br />If you have some hikes or excursions on your agenda, these pants will be your go to. Their breathable, 4-way stretch nylon fabric was built for movement and their durable, air permeable and water repellent properties will keep you protected from the elements. <a class="view-deal button" href="https://www.rei.com/product/229268/arcteryx-incendo-pants-mens" target="_blank" rel="nofollow" data-dimension112="7069a610-ce3a-11f1-92f0-c50a0fcc37f6" data-action="Deal Block" data-label="Incendo Pants (Men's)" data-dimension48="Incendo Pants (Men's)" data-dimension25="$90">View Deal</a></p></div><div class="product"><a data-dimension112="7069a67e-ce3a-11f1-9888-63f4d784fa7e" data-action="Deal Block" data-label="Satoro Merino Wool Long-Sleeve Top (Women's)" data-dimension48="Satoro Merino Wool Long-Sleeve Top (Women's)" data-dimension25="$95" href="https://www.rei.com/product/C11758/arcteryx-satoro-merino-wool-crew-neck-long-sleeve-base-layer-top-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="ZsZ2QSG882yqPoyEzEAnXk" name="Arc'teryx long sleeve" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZsZ2QSG882yqPoyEzEAnXk-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C11758/arcteryx-satoro-merino-wool-crew-neck-long-sleeve-base-layer-top-womens" target="_blank" rel="nofollow" data-dimension112="7069a67e-ce3a-11f1-9888-63f4d784fa7e" data-action="Deal Block" data-label="Satoro Merino Wool Long-Sleeve Top (Women's)" data-dimension48="Satoro Merino Wool Long-Sleeve Top (Women's)" data-dimension25="$95">Satoro Merino Wool Long-Sleeve Top (Women's): was $120 now $95</a></strong><br />This stylish long sleeve shirt is made with a soft, warm and breathable merino wool blend and it has a streamlined fit which layers easily. Its seams are also minimized to reduce irritation. It's the perfect shirt to help you move comfortably on hikes, runs and treks.<a class="view-deal button" href="https://www.rei.com/product/C11758/arcteryx-satoro-merino-wool-crew-neck-long-sleeve-base-layer-top-womens" target="_blank" rel="nofollow" data-dimension112="7069a67e-ce3a-11f1-9888-63f4d784fa7e" data-action="Deal Block" data-label="Satoro Merino Wool Long-Sleeve Top (Women's)" data-dimension48="Satoro Merino Wool Long-Sleeve Top (Women's)" data-dimension25="$95">View Deal</a></p></div><div class="product"><a data-dimension112="7069a6ec-ce3a-11f1-96d2-f1a6e1cf6262" data-action="Deal Block" data-label="Sima Hoody (Men's)" data-dimension48="Sima Hoody (Men's)" data-dimension25="$119" href="https://www.rei.com/product/C01372/arcteryx-sima-hoody-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1999px;"><p class="vanilla-image-block" style="padding-top:100.05%;"><img id="7ALJ3myuTiT2XsP4zXyHWg" name="Arc'teryx Sima" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/7ALJ3myuTiT2XsP4zXyHWg-1920-80.jpg" mos="" align="middle" fullscreen="" width="1999" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01372/arcteryx-sima-hoody-mens" target="_blank" rel="nofollow" data-dimension112="7069a6ec-ce3a-11f1-96d2-f1a6e1cf6262" data-action="Deal Block" data-label="Sima Hoody (Men's)" data-dimension48="Sima Hoody (Men's)" data-dimension25="$119">Sima Hoody (Men's): was $160 now $119</a></strong><br />This chic zip-up jacket is designed with backpackers and hikers in mind. Weighing just over six ounces, it's made from synthetic fabric with UPF 50+ sun protection. Nice and breathable, the fabric is also moisture-wicking to keep you dry.<a class="view-deal button" href="https://www.rei.com/product/C01372/arcteryx-sima-hoody-mens" target="_blank" rel="nofollow" data-dimension112="7069a6ec-ce3a-11f1-96d2-f1a6e1cf6262" data-action="Deal Block" data-label="Sima Hoody (Men's)" data-dimension48="Sima Hoody (Men's)" data-dimension25="$119">View Deal</a></p></div><div class="product"><a data-dimension112="7069a778-ce3a-11f1-a502-831417a06770" data-action="Deal Block" data-label="Squamish Hoody (Men's)" data-dimension48="Squamish Hoody (Men's)" data-dimension25="$119" href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="gU2HZNV4QV8x48bVFDMoVL" name="Arc'teryx Squamish" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gU2HZNV4QV8x48bVFDMoVL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow" data-dimension112="7069a778-ce3a-11f1-a502-831417a06770" data-action="Deal Block" data-label="Squamish Hoody (Men's)" data-dimension48="Squamish Hoody (Men's)" data-dimension25="$119">Squamish Hoody (Men's): was $200 now $119</a></strong><br />The Arc'teryx Squamish Hoody is completely windproof and finished with DWR, making it a versatile outer layer for those nippy wintry hikes. There's even a capped hood for keeping your face dry. There are currently six colors discounted at varying price points. <a class="view-deal button" href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow" data-dimension112="7069a778-ce3a-11f1-a502-831417a06770" data-action="Deal Block" data-label="Squamish Hoody (Men's)" data-dimension48="Squamish Hoody (Men's)" data-dimension25="$119">View Deal</a></p></div><div class="product"><a data-dimension112="7069a7f0-ce3a-11f1-92b4-f5a843a0d9a2" data-action="Deal Block" data-label="Atom Insulated Hoody (Men's)" data-dimension48="Atom Insulated Hoody (Men's)" data-dimension25="$199" href="https://www.rei.com/product/243175/arcteryx-atom-insulated-hoody-mens?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="hU57P6aYLHiVCsRgboxC6R" name="Arc'teryx" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hU57P6aYLHiVCsRgboxC6R-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/243175/arcteryx-atom-insulated-hoody-mens?" target="_blank" rel="nofollow" data-dimension112="7069a7f0-ce3a-11f1-92b4-f5a843a0d9a2" data-action="Deal Block" data-label="Atom Insulated Hoody (Men's)" data-dimension48="Atom Insulated Hoody (Men's)" data-dimension25="$199">Atom Insulated Hoody (Men's): was $300 now $199</a></strong><br />This deal is on the men’s Arc’teryx Atom Insulated Hoody, which is available in four different colors that are now on sale. Lightweight and weather-resistant, warm yet breathable, this high-tech piece of gorpware is fully worth the hype.<a class="view-deal button" href="https://www.rei.com/product/243175/arcteryx-atom-insulated-hoody-mens?" target="_blank" rel="nofollow" data-dimension112="7069a7f0-ce3a-11f1-92b4-f5a843a0d9a2" data-action="Deal Block" data-label="Atom Insulated Hoody (Men's)" data-dimension48="Atom Insulated Hoody (Men's)" data-dimension25="$199">View Deal</a></p></div><div class="product"><a data-dimension112="7069a8b8-ce3a-11f1-aac9-3bff2f05fec2" data-action="Deal Block" data-label="Beta SL Jacket (Men's)" data-dimension48="Beta SL Jacket (Men's)" data-dimension25="$299" href="https://www.rei.com/product/235112/arcteryx-beta-sl-jacket-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="qb97kzq9mCRC8aoRkEXVCX" name="Arc'teryx Beta" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/qb97kzq9mCRC8aoRkEXVCX-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/235112/arcteryx-beta-sl-jacket-mens" target="_blank" rel="nofollow" data-dimension112="7069a8b8-ce3a-11f1-aac9-3bff2f05fec2" data-action="Deal Block" data-label="Beta SL Jacket (Men's)" data-dimension48="Beta SL Jacket (Men's)" data-dimension25="$299">Beta SL Jacket (Men's): was $500 now $299</a></strong><br />Lightweight, comfortable and breathable, this durable waterproof and windproof jacket will protect you from the elements without sacrificing features or packability. It's a great option for layering or wearing on its own. <a class="view-deal button" href="https://www.rei.com/product/235112/arcteryx-beta-sl-jacket-mens" target="_blank" rel="nofollow" data-dimension112="7069a8b8-ce3a-11f1-aac9-3bff2f05fec2" data-action="Deal Block" data-label="Beta SL Jacket (Men's)" data-dimension48="Beta SL Jacket (Men's)" data-dimension25="$299">View Deal</a></p></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness/rei-is-taking-up-to-50-percent-off-best-selling-arcteryx-gear-for-fall-here-are-my-11-favorite-deals</link>
                                                                            <description>
                            <![CDATA[ REI is hosting a huge sale on Arc'teryx fall apparel. Here are my favorite deals to shop now from $38. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">dC9cK86mV49Zm5jHnam92N</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/XJWohJ2qmbomBLVhRBzewn-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 22 Oct 2026 17:33:49 +0000</pubDate>                                                                                                                                <updated>Fri, 23 Oct 2026 09:16:24 +0000</updated>
                                                                                                                                            <category><![CDATA[Fitness]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Olivia Halevy ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/YAg7Fmh9dGKbg3hULBMWiU-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Olivia is a Deals Writer at Tom’s Guide. She loves all things lifestyle, shopping and sourcing the best deals from some of the top brands, retailers and websites around. From fashion and beauty to smart home and tech, she has an eye for finding practical, stylish, and reasonably-priced items that help make life simpler (and a little more aesthetically-pleasing).&amp;nbsp;Olivia has over five years of experience writing lifestyle, commerce, and branded content for &lt;a href=&quot;http://patch.com/&quot;&gt;Patch.com&lt;/a&gt;. She&#039;s covered major shopping holidays like Amazon Prime Day, Black Friday and Cyber Monday. In her free time, she enjoys trying out new exercise classes, binge-watching the latest viral TV shows, cooking, spending time with family and taking long walks with her dog, Gus.&amp;nbsp;&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/XJWohJ2qmbomBLVhRBzewn-1920-80.jpg">
                                                            <media:credit><![CDATA[REI / edited by Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Arc&#039;teryx]]></media:description>                                                            <media:text><![CDATA[Arc&#039;teryx]]></media:text>
                                <media:title type="plain"><![CDATA[Arc&#039;teryx]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/XJWohJ2qmbomBLVhRBzewn-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Arc'teryx is commonly known for its winter gear, but many of its best-selling pieces are also great for fall. From lightweight layers to hiking pants and rain jackets, they have plenty of high-quality styles built for the changing seasons ahead. </p><p>Case in point: <a href="https://www.rei.com/b/arcteryx/f/scd-deals?" target="_blank" rel="nofollow">REI is currently knocking up to 50% off best-selling Arc'teryx apparel for fall</a>. Whether you’re planning alpine hikes, backcountry trail rides or you simply want to spend more time in the great outdoors, the Arc'teryx sale is the perfect opportunity to invest in top-tier gear for all your upcoming adventures. </p><p>So don't wait! Keep scrolling to check out the rest of my favorite finds from the Arc'teryx sale at REI.  </p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><a href="https://www.rei.com/b/arcteryx/f/scd-deals" target="_blank" rel="nofollow"><strong>shop all Arc'teryx deals at REI</strong></a></li><li><strong>Arc'teryx Taema Tank Top (Women's): </strong><a href="https://www.rei.com/product/C05677/arcteryx-taema-tank-top-womens" target="_blank" rel="nofollow"><strong>was $60 now $38</strong></a></li><li><strong>Arc'teryx Cormac Logo T-Shirt (Men's): </strong><a href="https://www.rei.com/product/C01312/arcteryx-cormac-logo-t-shirt-mens" target="_blank" rel="nofollow"><strong>was $80 now $39</strong></a></li><li><strong>Arc'teryx Cormac Crew Long-Sleeve Shirt (Men's): </strong><a href="https://www.rei.com/product/218811/arcteryx-cormac-crew-long-sleeve-shirt-mens?" target="_blank" rel="nofollow"><strong>was $80 now $55</strong></a></li><li><strong>Arc'teryx Satoro Merino Wool Long-Sleeve Top (Women's): </strong><a href="https://www.rei.com/product/C11758/arcteryx-satoro-merino-wool-crew-neck-long-sleeve-base-layer-top-womens" target="_blank" rel="nofollow"><strong>was $120 now $95</strong></a></li><li><strong>Arc'teryx Atom Insulated Hoody (Men's): </strong><a href="https://www.rei.com/product/243175/arcteryx-atom-insulated-hoody-mens?" target="_blank" rel="nofollow"><strong>was $300 now $199</strong></a></li><li><strong>Arc'teryx Beta SL Jacket (Men's): </strong><a href="https://www.rei.com/product/235112/arcteryx-beta-sl-jacket-mens" target="_blank" rel="nofollow"><strong>was $500 now $299</strong></a></li></ul><h3 class="article-body__section" id="section-arc-teryx-deals"><span>Arc'teryx Deals </span></h3><div class="product"><a data-dimension112="7069a3a4-ce3a-11f1-b31e-2f77c6693aab" data-action="Deal Block" data-label="Taema Tank Top (Women's)" data-dimension48="Taema Tank Top (Women's)" data-dimension25="$38" href="https://www.rei.com/product/C05677/arcteryx-taema-tank-top-womens" 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="rXhnnkZbPZd2ntrTrKECK3" name="Taema tank top" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/rXhnnkZbPZd2ntrTrKECK3-1920-80.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C05677/arcteryx-taema-tank-top-womens" target="_blank" rel="nofollow" data-dimension112="7069a3a4-ce3a-11f1-b31e-2f77c6693aab" data-action="Deal Block" data-label="Taema Tank Top (Women's)" data-dimension48="Taema Tank Top (Women's)" data-dimension25="$38">Taema Tank Top (Women's): was $60 now $38</a></strong><br />This racerback, crew neck tank top features a breathable fabric that wicks moisture away and dries quickly, making it perfect for longer hikes. It's soft, comfortable and built for performance. <a class="view-deal button" href="https://www.rei.com/product/C05677/arcteryx-taema-tank-top-womens" target="_blank" rel="nofollow" data-dimension112="7069a3a4-ce3a-11f1-b31e-2f77c6693aab" data-action="Deal Block" data-label="Taema Tank Top (Women's)" data-dimension48="Taema Tank Top (Women's)" data-dimension25="$38">View Deal</a></p></div><div class="product"><a data-dimension112="7069a43a-ce3a-11f1-92c0-15ed0468cebd" data-action="Deal Block" data-label="Cormac Logo T-Shirt (Men's)" data-dimension48="Cormac Logo T-Shirt (Men's)" data-dimension25="$39" href="https://www.rei.com/product/C01312/arcteryx-cormac-logo-t-shirt-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="jJvHixb5ZKWc2ciLwkBt3J" name="Arc'teryx tee" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jJvHixb5ZKWc2ciLwkBt3J-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01312/arcteryx-cormac-logo-t-shirt-mens" target="_blank" rel="nofollow" data-dimension112="7069a43a-ce3a-11f1-92c0-15ed0468cebd" data-action="Deal Block" data-label="Cormac Logo T-Shirt (Men's)" data-dimension48="Cormac Logo T-Shirt (Men's)" data-dimension25="$39">Cormac Logo T-Shirt (Men's): was $80 now $39</a></strong><br />If you're a big Arc'teryx fan (who isn't?) then you'll want to grab this t-shirt. It has the Arc'teryx logo front and center and is made of comfortable, breathable cotton jersey fabric.<a class="view-deal button" href="https://www.rei.com/product/C01312/arcteryx-cormac-logo-t-shirt-mens" target="_blank" rel="nofollow" data-dimension112="7069a43a-ce3a-11f1-92c0-15ed0468cebd" data-action="Deal Block" data-label="Cormac Logo T-Shirt (Men's)" data-dimension48="Cormac Logo T-Shirt (Men's)" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="6afc31ba-cec2-11f1-b54e-012b3a9d2ab0" data-action="Deal Block" data-label="Small Bird Cap" data-dimension48="Small Bird Cap" data-dimension25="$39" href="https://www.rei.com/product/C11817/arcteryx-small-bird-cap" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="GhyZp7wzR7ogFWo5rp5cfZ" name="Arc'teryx hst" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/GhyZp7wzR7ogFWo5rp5cfZ-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C11817/arcteryx-small-bird-cap" target="_blank" rel="nofollow" data-dimension112="6afc31ba-cec2-11f1-b54e-012b3a9d2ab0" data-action="Deal Block" data-label="Small Bird Cap" data-dimension48="Small Bird Cap" data-dimension25="$39">Small Bird Cap: was $50 now $39</a></strong><br />Need a new hat for the trails? The Arc'teryx Small Bird hat is made with breathable, stretchy material and a soft, quick-drying headband that will keep your head feeling airy and dry. It will get the job done on the toughest of routes. <a class="view-deal button" href="https://www.rei.com/product/C11817/arcteryx-small-bird-cap" target="_blank" rel="nofollow" data-dimension112="6afc31ba-cec2-11f1-b54e-012b3a9d2ab0" data-action="Deal Block" data-label="Small Bird Cap" data-dimension48="Small Bird Cap" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="7069a4bc-ce3a-11f1-b123-35461167aea6" data-action="Deal Block" data-label="Word Toque (Unisex)" data-dimension48="Word Toque (Unisex)" data-dimension25="$44" href="https://www.rei.com/product/C11815/arcteryx-color-block-toque" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="KFMjo5N4Bne6DPzoJtjey5" name="Arc'teryx deals" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/KFMjo5N4Bne6DPzoJtjey5-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C11815/arcteryx-color-block-toque" target="_blank" rel="nofollow" data-dimension112="7069a4bc-ce3a-11f1-b123-35461167aea6" data-action="Deal Block" data-label="Word Toque (Unisex)" data-dimension48="Word Toque (Unisex)" data-dimension25="$44">Word Toque (Unisex): was $55 now $44</a></strong><br />A cozy, cuffed beanie never goes out of style, and with temperatures dropping, this blue staple is ready to keep you warm and fashionable, all fall and winter long.<a class="view-deal button" href="https://www.rei.com/product/C11815/arcteryx-color-block-toque" target="_blank" rel="nofollow" data-dimension112="7069a4bc-ce3a-11f1-b123-35461167aea6" data-action="Deal Block" data-label="Word Toque (Unisex)" data-dimension48="Word Toque (Unisex)" data-dimension25="$44">View Deal</a></p></div><div class="product"><a data-dimension112="6afc323c-cec2-11f1-b339-7141bbc60ef7" data-action="Deal Block" data-label="Base Layer Bottoms (Women's)" data-dimension48="Base Layer Bottoms (Women's)" data-dimension25="$49" href="https://www.rei.com/product/209252/arcteryx-rho-base-layer-bottoms-womens?color=BLACK" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:588px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="rn5oNYv8T4jW6o67MGfR9B" name="Rho Base Layer" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/rn5oNYv8T4jW6o67MGfR9B-1920-80.jpg" mos="" align="middle" fullscreen="" width="588" height="588" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/209252/arcteryx-rho-base-layer-bottoms-womens?color=BLACK" target="_blank" rel="nofollow" data-dimension112="6afc323c-cec2-11f1-b339-7141bbc60ef7" data-action="Deal Block" data-label="Base Layer Bottoms (Women's)" data-dimension48="Base Layer Bottoms (Women's)" data-dimension25="$49">Base Layer Bottoms (Women's): was $100 now $49</a></strong><br />These heavyweight bottoms from Arc’teryx just got a massive discount. Arc’teryx’s Polygiene treatment helps with odor, while the Torrent brushed fleece is soft against your skin. <a class="view-deal button" href="https://www.rei.com/product/209252/arcteryx-rho-base-layer-bottoms-womens?color=BLACK" target="_blank" rel="nofollow" data-dimension112="6afc323c-cec2-11f1-b339-7141bbc60ef7" data-action="Deal Block" data-label="Base Layer Bottoms (Women's)" data-dimension48="Base Layer Bottoms (Women's)" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="7069a52a-ce3a-11f1-a050-ed45b7697e73" data-action="Deal Block" data-label="Cormac Crew Long-Sleeve Shirt (Men's)" data-dimension48="Cormac Crew Long-Sleeve Shirt (Men's)" data-dimension25="$55" href="https://www.rei.com/product/218811/arcteryx-cormac-crew-long-sleeve-shirt-mens?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1450px;"><p class="vanilla-image-block" style="padding-top:103.45%;"><img id="9ovahzghZXKKQwERkhLbWH" name="cormac" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/9ovahzghZXKKQwERkhLbWH-1920-80.jpg" mos="" align="middle" fullscreen="" width="1450" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/218811/arcteryx-cormac-crew-long-sleeve-shirt-mens?" target="_blank" rel="nofollow" data-dimension112="7069a52a-ce3a-11f1-a050-ed45b7697e73" data-action="Deal Block" data-label="Cormac Crew Long-Sleeve Shirt (Men's)" data-dimension48="Cormac Crew Long-Sleeve Shirt (Men's)" data-dimension25="$55">Cormac Crew Long-Sleeve Shirt (Men's): was $80 now $55</a></strong><br />This long-sleeved exercise top was inspired by running apparel, but then adapted to make it suitable for mountain-based high-intensity activities. It's breathable, maximizes airflow, and is designed to reduce chafing. <a class="view-deal button" href="https://www.rei.com/product/218811/arcteryx-cormac-crew-long-sleeve-shirt-mens?" target="_blank" rel="nofollow" data-dimension112="7069a52a-ce3a-11f1-a050-ed45b7697e73" data-action="Deal Block" data-label="Cormac Crew Long-Sleeve Shirt (Men's)" data-dimension48="Cormac Crew Long-Sleeve Shirt (Men's)" data-dimension25="$55">View Deal</a></p></div><div class="product"><a data-dimension112="7069a598-ce3a-11f1-9ea6-fde28fa3d81e" data-action="Deal Block" data-label="Cranbrook Hat" data-dimension48="Cranbrook Hat" data-dimension25="$68" href="https://www.rei.com/product/246886/arcteryx-cranbrook-hat" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:588px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="x8NaJfMivLbsqngaKxLaKZ" name="Arc'teryx bucket hat" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/x8NaJfMivLbsqngaKxLaKZ-1920-80.jpg" mos="" align="middle" fullscreen="" width="588" height="588" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>If you have some backcountry adventures planned, this is the hat you'll want to bring along. The Arc'teryx Cranbrook hat has a wide brim that shades your face, ears and neck from the sun, and it's ventilated to keep you nice and cool. <a class="view-deal button" href="https://www.rei.com/product/246886/arcteryx-cranbrook-hat" target="_blank" rel="nofollow" data-dimension112="7069a598-ce3a-11f1-9ea6-fde28fa3d81e" data-action="Deal Block" data-label="Cranbrook Hat" data-dimension48="Cranbrook Hat" data-dimension25="$68">View Deal</a></p></div><div class="product"><a data-dimension112="7069a610-ce3a-11f1-92f0-c50a0fcc37f6" data-action="Deal Block" data-label="Incendo Pants (Men's)" data-dimension48="Incendo Pants (Men's)" data-dimension25="$90" href="https://www.rei.com/product/229268/arcteryx-incendo-pants-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="KfdPeGj43M8ocSgpPLLmjZ" name="incendo" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/KfdPeGj43M8ocSgpPLLmjZ-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/229268/arcteryx-incendo-pants-mens" target="_blank" rel="nofollow" data-dimension112="7069a610-ce3a-11f1-92f0-c50a0fcc37f6" data-action="Deal Block" data-label="Incendo Pants (Men's)" data-dimension48="Incendo Pants (Men's)" data-dimension25="$90">Incendo Pants (Men's): was $130 now $90</a></strong><br />If you have some hikes or excursions on your agenda, these pants will be your go to. Their breathable, 4-way stretch nylon fabric was built for movement and their durable, air permeable and water repellent properties will keep you protected from the elements. <a class="view-deal button" href="https://www.rei.com/product/229268/arcteryx-incendo-pants-mens" target="_blank" rel="nofollow" data-dimension112="7069a610-ce3a-11f1-92f0-c50a0fcc37f6" data-action="Deal Block" data-label="Incendo Pants (Men's)" data-dimension48="Incendo Pants (Men's)" data-dimension25="$90">View Deal</a></p></div><div class="product"><a data-dimension112="7069a67e-ce3a-11f1-9888-63f4d784fa7e" data-action="Deal Block" data-label="Satoro Merino Wool Long-Sleeve Top (Women's)" data-dimension48="Satoro Merino Wool Long-Sleeve Top (Women's)" data-dimension25="$95" href="https://www.rei.com/product/C11758/arcteryx-satoro-merino-wool-crew-neck-long-sleeve-base-layer-top-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="ZsZ2QSG882yqPoyEzEAnXk" name="Arc'teryx long sleeve" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZsZ2QSG882yqPoyEzEAnXk-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C11758/arcteryx-satoro-merino-wool-crew-neck-long-sleeve-base-layer-top-womens" target="_blank" rel="nofollow" data-dimension112="7069a67e-ce3a-11f1-9888-63f4d784fa7e" data-action="Deal Block" data-label="Satoro Merino Wool Long-Sleeve Top (Women's)" data-dimension48="Satoro Merino Wool Long-Sleeve Top (Women's)" data-dimension25="$95">Satoro Merino Wool Long-Sleeve Top (Women's): was $120 now $95</a></strong><br />This stylish long sleeve shirt is made with a soft, warm and breathable merino wool blend and it has a streamlined fit which layers easily. Its seams are also minimized to reduce irritation. It's the perfect shirt to help you move comfortably on hikes, runs and treks.<a class="view-deal button" href="https://www.rei.com/product/C11758/arcteryx-satoro-merino-wool-crew-neck-long-sleeve-base-layer-top-womens" target="_blank" rel="nofollow" data-dimension112="7069a67e-ce3a-11f1-9888-63f4d784fa7e" data-action="Deal Block" data-label="Satoro Merino Wool Long-Sleeve Top (Women's)" data-dimension48="Satoro Merino Wool Long-Sleeve Top (Women's)" data-dimension25="$95">View Deal</a></p></div><div class="product"><a data-dimension112="7069a6ec-ce3a-11f1-96d2-f1a6e1cf6262" data-action="Deal Block" data-label="Sima Hoody (Men's)" data-dimension48="Sima Hoody (Men's)" data-dimension25="$119" href="https://www.rei.com/product/C01372/arcteryx-sima-hoody-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1999px;"><p class="vanilla-image-block" style="padding-top:100.05%;"><img id="7ALJ3myuTiT2XsP4zXyHWg" name="Arc'teryx Sima" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/7ALJ3myuTiT2XsP4zXyHWg-1920-80.jpg" mos="" align="middle" fullscreen="" width="1999" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01372/arcteryx-sima-hoody-mens" target="_blank" rel="nofollow" data-dimension112="7069a6ec-ce3a-11f1-96d2-f1a6e1cf6262" data-action="Deal Block" data-label="Sima Hoody (Men's)" data-dimension48="Sima Hoody (Men's)" data-dimension25="$119">Sima Hoody (Men's): was $160 now $119</a></strong><br />This chic zip-up jacket is designed with backpackers and hikers in mind. Weighing just over six ounces, it's made from synthetic fabric with UPF 50+ sun protection. Nice and breathable, the fabric is also moisture-wicking to keep you dry.<a class="view-deal button" href="https://www.rei.com/product/C01372/arcteryx-sima-hoody-mens" target="_blank" rel="nofollow" data-dimension112="7069a6ec-ce3a-11f1-96d2-f1a6e1cf6262" data-action="Deal Block" data-label="Sima Hoody (Men's)" data-dimension48="Sima Hoody (Men's)" data-dimension25="$119">View Deal</a></p></div><div class="product"><a data-dimension112="7069a778-ce3a-11f1-a502-831417a06770" data-action="Deal Block" data-label="Squamish Hoody (Men's)" data-dimension48="Squamish Hoody (Men's)" data-dimension25="$119" href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="gU2HZNV4QV8x48bVFDMoVL" name="Arc'teryx Squamish" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gU2HZNV4QV8x48bVFDMoVL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow" data-dimension112="7069a778-ce3a-11f1-a502-831417a06770" data-action="Deal Block" data-label="Squamish Hoody (Men's)" data-dimension48="Squamish Hoody (Men's)" data-dimension25="$119">Squamish Hoody (Men's): was $200 now $119</a></strong><br />The Arc'teryx Squamish Hoody is completely windproof and finished with DWR, making it a versatile outer layer for those nippy wintry hikes. There's even a capped hood for keeping your face dry. There are currently six colors discounted at varying price points. <a class="view-deal button" href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow" data-dimension112="7069a778-ce3a-11f1-a502-831417a06770" data-action="Deal Block" data-label="Squamish Hoody (Men's)" data-dimension48="Squamish Hoody (Men's)" data-dimension25="$119">View Deal</a></p></div><div class="product"><a data-dimension112="7069a7f0-ce3a-11f1-92b4-f5a843a0d9a2" data-action="Deal Block" data-label="Atom Insulated Hoody (Men's)" data-dimension48="Atom Insulated Hoody (Men's)" data-dimension25="$199" href="https://www.rei.com/product/243175/arcteryx-atom-insulated-hoody-mens?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="hU57P6aYLHiVCsRgboxC6R" name="Arc'teryx" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hU57P6aYLHiVCsRgboxC6R-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/243175/arcteryx-atom-insulated-hoody-mens?" target="_blank" rel="nofollow" data-dimension112="7069a7f0-ce3a-11f1-92b4-f5a843a0d9a2" data-action="Deal Block" data-label="Atom Insulated Hoody (Men's)" data-dimension48="Atom Insulated Hoody (Men's)" data-dimension25="$199">Atom Insulated Hoody (Men's): was $300 now $199</a></strong><br />This deal is on the men’s Arc’teryx Atom Insulated Hoody, which is available in four different colors that are now on sale. Lightweight and weather-resistant, warm yet breathable, this high-tech piece of gorpware is fully worth the hype.<a class="view-deal button" href="https://www.rei.com/product/243175/arcteryx-atom-insulated-hoody-mens?" target="_blank" rel="nofollow" data-dimension112="7069a7f0-ce3a-11f1-92b4-f5a843a0d9a2" data-action="Deal Block" data-label="Atom Insulated Hoody (Men's)" data-dimension48="Atom Insulated Hoody (Men's)" data-dimension25="$199">View Deal</a></p></div><div class="product"><a data-dimension112="7069a8b8-ce3a-11f1-aac9-3bff2f05fec2" data-action="Deal Block" data-label="Beta SL Jacket (Men's)" data-dimension48="Beta SL Jacket (Men's)" data-dimension25="$299" href="https://www.rei.com/product/235112/arcteryx-beta-sl-jacket-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="qb97kzq9mCRC8aoRkEXVCX" name="Arc'teryx Beta" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/qb97kzq9mCRC8aoRkEXVCX-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/235112/arcteryx-beta-sl-jacket-mens" target="_blank" rel="nofollow" data-dimension112="7069a8b8-ce3a-11f1-aac9-3bff2f05fec2" data-action="Deal Block" data-label="Beta SL Jacket (Men's)" data-dimension48="Beta SL Jacket (Men's)" data-dimension25="$299">Beta SL Jacket (Men's): was $500 now $299</a></strong><br />Lightweight, comfortable and breathable, this durable waterproof and windproof jacket will protect you from the elements without sacrificing features or packability. It's a great option for layering or wearing on its own. <a class="view-deal button" href="https://www.rei.com/product/235112/arcteryx-beta-sl-jacket-mens" target="_blank" rel="nofollow" data-dimension112="7069a8b8-ce3a-11f1-aac9-3bff2f05fec2" data-action="Deal Block" data-label="Beta SL Jacket (Men's)" data-dimension48="Beta SL Jacket (Men's)" data-dimension25="$299">View Deal</a></p></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 12 women's sneaker deals on Nike, New Balance, Puma and more – from $56 ]]></title>
                                                                                                <dc:content><![CDATA[ <p>If you're looking to add some new sneakers to your daily rotation, then make sure to check out Amazon. The online retailer has a huge range of offers on shoes right now, including some great sneakers for women.</p><p>For this article, I've rounded up 12 styles from a range of cool brands, including New Balance, Puma, Nike, and more. All of these picks are currently discounted, with up to 50% off the retail price of some pairs.</p><p>Amazon deals change quickly, so if you spot something that you like, run, don't walk, to these brilliant deals and add some new flair to your shoe collection today.</p>        <div class="featured_product_block featured_block_hero" data-id="72c5eb44-ce03-11f1-a71a-3b5b948e0431">            <a href="https://www.amazon.com/adidas-Womens-Gamecourt-Tennis-WhiteZeroMetallicWhite/dp/B0FW51R3X1/" data-model-name="Adidas Gamecourt 3 Tennis Sneakers" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check="" style='padding-top:144.51%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/M4FmFLUS9VCmje8Br33GmK.jpg" alt="Adidas Women's Gamecourt 3 Tennis, White/zero Metallic/white, 9" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Adidas Gamecourt 3 Tennis Sneakers</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5ebc6-ce03-11f1-8a52-51e8d962a610">            <a href="https://www.amazon.com/Karl-Lagerfeld-Paris-Womens-Sneaker/dp/B091V6SQQC/" data-model-name="Karl Lagerfeld Women's Cate Lace Up Sneaker" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check="" style='padding-top:66.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/CysN4sKE5mJaKp5ULohK2L.jpg" alt="Karl Lagerfeld Women's Cate Lace Up Sneaker, Black, 6.5" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Karl Lagerfeld Women's Cate Lace Up Sneaker</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5ec3e-ce03-11f1-a932-65458be5edd4">            <a href="https://www.amazon.com/ASICS-Womens-Gel-Pulse-Running-MORGANITE/dp/B0FV7M4Z2R/" data-model-name="Asics Women's Gel-Venture" 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/DKQ6pgJ6ccsYyzfhdX5M8L.jpg" alt="Asics Women's Gel-Venture 11 Running Shoes, 8.5, Black/morganite" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Asics Women's Gel-Venture</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5ecb6-ce03-11f1-b695-63f5dc80f1f7">            <a href="https://www.amazon.com/Nike-Womens-Cortez-Sneakers-Varsity/dp/B0D1YFQSBK/" data-model-name="Nike Women's Cortez Sneakers" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check="" style='padding-top:75.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/ZxE3d5fcHu2AjqBiQTZ7WL.jpg" alt="Nike Women's Cortez Sneakers, White/varsity Red/varsity Blue, 8.5 Medium Us" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Nike Women's Cortez Sneakers</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5ed2e-ce03-11f1-a507-e3717bbc341d">            <a href="https://www.amazon.com/Franco-Sarto-Womens-Felina-Sneaker/dp/B0FXBS1RHK/" data-model-name="Franco Sarto Women's Felina Sneaker" 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/cQnF9So9g2wGQrFw6JeijL.jpg" alt="Franco Sarto Women's Felina Sneaker Cloud White Nylon 7.5 M" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Franco Sarto Women's Felina Sneaker</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5ed9c-ce03-11f1-bd82-51516f27c370">            <a href="https://www.amazon.com/New-Balance-Womens-Sneaker-Nimbus/dp/B093QK8S8R/" data-model-name="New Balance Women's 574 Core Sneaker" 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/TuiF9YxC9KhqqkTdS3aZmL.jpg" alt="New Balance Women's 574 Core Sneaker, Nimbus Cloud/nb White, 7 B" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">New Balance Women's 574 Core Sneaker</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5ee14-ce03-11f1-b74d-55388f84e1a3">            <a href="https://www.amazon.com/New-Balance-Womens-Delray-Boysenberry/dp/B0DJV366W9/" data-model-name="New Balance FuelCell Delray V2 Tennis Sneakers" 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/CQDpCoQ9jJi5ARdGtwaUxL.jpg" alt="New Balance Women's Coco Delray V2 Hard Court Tennis Shoe, Apollo Gold/boysenberry, 8 M" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">New Balance FuelCell Delray V2 Tennis Sneakers</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5ee82-ce03-11f1-8257-61eec769a56c">            <a href="https://www.amazon.com/Nike-Womens-Sneaker-Black-8/dp/B0BS6N47FL/" data-model-name="Nike Women's W Free Metcon Training Shoes" 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/DDgGKRMd2v2Nsb5mGu4c5M.jpg" alt="Nike Women's W Free Metcon 5 Training Shoes, Black White Anthracite, 8" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Nike Women's W Free Metcon Training Shoes</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5eefa-ce03-11f1-9142-bfffe83a5537">            <a href="https://www.amazon.com/SKECHERS-Womens-Pickleball-Viper-Sneaker/dp/B0DWQG6Y6Z/" data-model-name="Skechers Women's Pickleball Viper Court Pro 2.0 Sneaker" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check="" style='padding-top:75.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/Q364zk9PDxe7mLapjzAaAM.jpg" alt="Skechers Women's Pickleball Viper Court Pro 2.0 Sneaker, Hot Pink, 8 Medium" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Skechers Women's Pickleball Viper Court Pro 2.0 Sneaker</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5ef68-ce03-11f1-b63e-9f37c65df397">            <a href="https://www.amazon.com/PUMA-Womens-Speedcat-Shoes-Royal-Puma/dp/B0FBK4RRQT/" data-model-name="Puma Women's Speedcat OG Shoes" 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/5Zr43Tso3EfpngXfTrTSkM.jpg" alt="Puma Women's Speedcat Og Shoes, Puma Team Royal-Puma White, 9" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Puma Women's Speedcat OG Shoes</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5efe0-ce03-11f1-ab26-f19a4950aac0">            <a href="https://www.amazon.com/Nike-Womens-Sneakers-White-Medium/dp/B08Q9Q27GQ/" data-model-name="Nike Women's Dunk Low Sneakers" 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/2aH7ogH8AdupJ8GJPpJenM.jpg" alt="Nike Women's Dunk Low Sneakers, White/black/white, 6 Medium Us" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Nike Women's Dunk Low Sneakers</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5f058-ce03-11f1-a409-ed32186f7e6c">            <a href="https://www.amazon.com/Brooks-Glycerin-Neutral-Running-Walking/dp/B0F5N9VN8S/" data-model-name="Brooks Women's Glycerin Flex Neutral Running Shoe" 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/iiqbJvnHTzLD8DQQAtW8uM.jpg" alt="Brooks Women’s Glycerin Flex Neutral Running &amp; Walking Shoe - White/black/gum - 9 Medium" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Brooks Women's Glycerin Flex Neutral Running Shoe</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/running/12-womens-sneaker-deals-on-nike-new-balance-puma-and-more-from-usd56</link>
                                                                            <description>
                            <![CDATA[ Add some cool new sneakers to your collection with these deals on 12 different styles for women– with up to 50% off the retail price. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">pogEYZJjHu7DvZFBrWBCSN</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/PjHjGSYLRAFYGuT9PN9nVZ-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 22 Oct 2026 14:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Running]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Will Salmon ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/HpRWP7Mh9ErgRGoTvZBbBJ-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Will Salmon is Tom&#039;s Guide&#039;s Collections Editor, curating advice on the best products to spend your money on. Will has been writing about tech and entertainment for almost 20 years, including stints as GamesRadar+&#039;s Streaming Editor, editing comics website Newsarama, and writing for lots and lots of magazines.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/PjHjGSYLRAFYGuT9PN9nVZ-1920-80.jpg">
                                                            <media:credit><![CDATA[Franco Sarto, New Balance, Asics, Puma, Nike / Edited with Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[A selection of womens&#039; sneakers.]]></media:description>                                                            <media:text><![CDATA[A selection of womens&#039; sneakers.]]></media:text>
                                <media:title type="plain"><![CDATA[A selection of womens&#039; sneakers.]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/PjHjGSYLRAFYGuT9PN9nVZ-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>If you're looking to add some new sneakers to your daily rotation, then make sure to check out Amazon. The online retailer has a huge range of offers on shoes right now, including some great sneakers for women.</p><p>For this article, I've rounded up 12 styles from a range of cool brands, including New Balance, Puma, Nike, and more. All of these picks are currently discounted, with up to 50% off the retail price of some pairs.</p><p>Amazon deals change quickly, so if you spot something that you like, run, don't walk, to these brilliant deals and add some new flair to your shoe collection today.</p>        <div class="featured_product_block featured_block_hero" data-id="72c5eb44-ce03-11f1-a71a-3b5b948e0431">            <a href="https://www.amazon.com/adidas-Womens-Gamecourt-Tennis-WhiteZeroMetallicWhite/dp/B0FW51R3X1/" data-model-name="Adidas Gamecourt 3 Tennis Sneakers" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check="" style='padding-top:144.51%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/M4FmFLUS9VCmje8Br33GmK.jpg" alt="Adidas Women's Gamecourt 3 Tennis, White/zero Metallic/white, 9" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Adidas Gamecourt 3 Tennis Sneakers</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5ebc6-ce03-11f1-8a52-51e8d962a610">            <a href="https://www.amazon.com/Karl-Lagerfeld-Paris-Womens-Sneaker/dp/B091V6SQQC/" data-model-name="Karl Lagerfeld Women's Cate Lace Up Sneaker" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check="" style='padding-top:66.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/CysN4sKE5mJaKp5ULohK2L.jpg" alt="Karl Lagerfeld Women's Cate Lace Up Sneaker, Black, 6.5" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Karl Lagerfeld Women's Cate Lace Up Sneaker</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5ec3e-ce03-11f1-a932-65458be5edd4">            <a href="https://www.amazon.com/ASICS-Womens-Gel-Pulse-Running-MORGANITE/dp/B0FV7M4Z2R/" data-model-name="Asics Women's Gel-Venture" 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/DKQ6pgJ6ccsYyzfhdX5M8L.jpg" alt="Asics Women's Gel-Venture 11 Running Shoes, 8.5, Black/morganite" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Asics Women's Gel-Venture</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5ecb6-ce03-11f1-b695-63f5dc80f1f7">            <a href="https://www.amazon.com/Nike-Womens-Cortez-Sneakers-Varsity/dp/B0D1YFQSBK/" data-model-name="Nike Women's Cortez Sneakers" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check="" style='padding-top:75.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/ZxE3d5fcHu2AjqBiQTZ7WL.jpg" alt="Nike Women's Cortez Sneakers, White/varsity Red/varsity Blue, 8.5 Medium Us" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Nike Women's Cortez Sneakers</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5ed2e-ce03-11f1-a507-e3717bbc341d">            <a href="https://www.amazon.com/Franco-Sarto-Womens-Felina-Sneaker/dp/B0FXBS1RHK/" data-model-name="Franco Sarto Women's Felina Sneaker" 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/cQnF9So9g2wGQrFw6JeijL.jpg" alt="Franco Sarto Women's Felina Sneaker Cloud White Nylon 7.5 M" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Franco Sarto Women's Felina Sneaker</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5ed9c-ce03-11f1-bd82-51516f27c370">            <a href="https://www.amazon.com/New-Balance-Womens-Sneaker-Nimbus/dp/B093QK8S8R/" data-model-name="New Balance Women's 574 Core Sneaker" 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/TuiF9YxC9KhqqkTdS3aZmL.jpg" alt="New Balance Women's 574 Core Sneaker, Nimbus Cloud/nb White, 7 B" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">New Balance Women's 574 Core Sneaker</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5ee14-ce03-11f1-b74d-55388f84e1a3">            <a href="https://www.amazon.com/New-Balance-Womens-Delray-Boysenberry/dp/B0DJV366W9/" data-model-name="New Balance FuelCell Delray V2 Tennis Sneakers" 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/CQDpCoQ9jJi5ARdGtwaUxL.jpg" alt="New Balance Women's Coco Delray V2 Hard Court Tennis Shoe, Apollo Gold/boysenberry, 8 M" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">New Balance FuelCell Delray V2 Tennis Sneakers</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5ee82-ce03-11f1-8257-61eec769a56c">            <a href="https://www.amazon.com/Nike-Womens-Sneaker-Black-8/dp/B0BS6N47FL/" data-model-name="Nike Women's W Free Metcon Training Shoes" 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/DDgGKRMd2v2Nsb5mGu4c5M.jpg" alt="Nike Women's W Free Metcon 5 Training Shoes, Black White Anthracite, 8" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Nike Women's W Free Metcon Training Shoes</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5eefa-ce03-11f1-9142-bfffe83a5537">            <a href="https://www.amazon.com/SKECHERS-Womens-Pickleball-Viper-Sneaker/dp/B0DWQG6Y6Z/" data-model-name="Skechers Women's Pickleball Viper Court Pro 2.0 Sneaker" data-model-brand="" ><div class='product-image-widthsetter'><p class='vanilla-image-block' data-bordeaux-image-check="" style='padding-top:75.00%';><img style="width: 100%" class="featured_image" src="https://cdn.mos.cms.futurecdn.net/Q364zk9PDxe7mLapjzAaAM.jpg" alt="Skechers Women's Pickleball Viper Court Pro 2.0 Sneaker, Hot Pink, 8 Medium" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Skechers Women's Pickleball Viper Court Pro 2.0 Sneaker</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5ef68-ce03-11f1-b63e-9f37c65df397">            <a href="https://www.amazon.com/PUMA-Womens-Speedcat-Shoes-Royal-Puma/dp/B0FBK4RRQT/" data-model-name="Puma Women's Speedcat OG Shoes" 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/5Zr43Tso3EfpngXfTrTSkM.jpg" alt="Puma Women's Speedcat Og Shoes, Puma Team Royal-Puma White, 9" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Puma Women's Speedcat OG Shoes</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5efe0-ce03-11f1-ab26-f19a4950aac0">            <a href="https://www.amazon.com/Nike-Womens-Sneakers-White-Medium/dp/B08Q9Q27GQ/" data-model-name="Nike Women's Dunk Low Sneakers" 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/2aH7ogH8AdupJ8GJPpJenM.jpg" alt="Nike Women's Dunk Low Sneakers, White/black/white, 6 Medium Us" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Nike Women's Dunk Low Sneakers</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>        <div class="featured_product_block featured_block_hero" data-id="72c5f058-ce03-11f1-a409-ed32186f7e6c">            <a href="https://www.amazon.com/Brooks-Glycerin-Neutral-Running-Walking/dp/B0F5N9VN8S/" data-model-name="Brooks Women's Glycerin Flex Neutral Running Shoe" 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/iiqbJvnHTzLD8DQQAtW8uM.jpg" alt="Brooks Women’s Glycerin Flex Neutral Running &amp; Walking Shoe - White/black/gum - 9 Medium" /></p></div></a>            <div class="featured_product_details_wrapper">                <div class="featured_product_title_wrapper">                                                                                <div class="featured__title">Brooks Women's Glycerin Flex Neutral Running Shoe</div>                                    </div>                <div class="subtitle__description">                                                            <p></p>                </div>                            </div>        </div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ We named the Nike Pegasus 42 the best value running shoe on the market, and it's 42% off right now — plus 17 more of our favorite Nike running shoe deals ]]></title>
                                                                                                <dc:content><![CDATA[ <p>It's a great day to buy a new pair of running shoes — even if your wallet is feeling the pinch. Don't hang around, the <a href="https://www.tomsguide.com/best-picks/best-running-shoes">best value running shoes</a> we've tested just got a big price cut!</p><p>The <a href="https://www.nike.com/t/pegasus-42-mens-road-running-shoes-S1bYkOza/IB1873-107" target="_blank" rel="nofollow">Nike Pegasus 42 are on sale from $82 at Nike</a>. These were already excellent value at full price, and with 42% off (a fitting discount for the 42nd version of the shoe) they're an absolute steal. They're versatile, smooth and great for both beginners and experienced runners alike.</p><p><strong>Note: </strong>prices vary depending on the size and color you choose. To find the best deals, check out any different color options available in your size. For more, see our <a href="https://www.tomsguide.com/wellness/fitness/nike-promo-codes">Nike promo codes</a>.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><a href="https://www.amazon.com/stores/page/E9C7C6A6-9A88-4959-A67F-4D44FC67320F" target="_blank" rel="nofollow"><strong>shop Nike deals at Amazon</strong></a><strong></strong></li><li><strong>Nike Victori One Slides (Men's): </strong><a href="https://www.nike.com/t/victori-one-mens-slides-vrTGLL/CN9675-304" target="_blank" rel="nofollow"><strong>was $37 now from $27</strong></a></li><li><strong>Nike Uplift Sc Shoes (Women's): </strong><a href="https://www.amazon.com/Nike-Womens-Uplift-Sneaker-Black/dp/B0F13DYVP8" target="_blank" rel="nofollow"><strong>was $70 now from $49</strong></a></li><li><strong>Nike Downshifter 14 (Men's): </strong><a href="https://www.nike.com/t/downshifter-14-mens-road-running-shoe-wrouoOtz/IB1895-108" target="_blank" rel="nofollow"><strong>was $80 now from $49</strong></a></li><li><strong>Nike Flex Train Workout Shoes (Men's): </strong><a href="https://www.amazon.com/Nike-Train-Sneaker-Safety-Orange/dp/B0FBS23WGF" target="_blank" rel="nofollow"><strong>was $80 now from $59</strong></a></li><li><strong>Nike Pegasus 42 (Men's): </strong><a href="https://www.nike.com/t/pegasus-42-mens-road-running-shoes-S1bYkOza/IB1873-107" target="_blank" rel="nofollow"><strong>was $145 now from $82</strong></a><br /><strong>Nike Zoom Fly 6 (Men's): </strong><a href="https://www.nike.com/t/zoom-fly-6-mens-road-racing-shoes-wn2ALjkm/IV6296-635" target="_blank" rel="nofollow"><strong>was $190 now from $143</strong></a></li><li><strong>Nike Alphafly 3 (Women's): </strong><a href="https://www.nike.com/t/alphafly-3-womens-road-racing-shoes-LQX5b4" target="_blank" rel="nofollow"><strong>was $295 now from $221</strong></a></li></ul><h3 class="article-body__section" id="section-nike-footwear-deals"><span>Nike Footwear Deals</span></h3><div class="product"><a data-dimension112="c590e140-ce16-11f1-b8f5-2165faf7167e" data-action="Deal Block" data-label="Victori One Slides (Men's)" data-dimension48="Victori One Slides (Men's)" data-dimension25="$27" href="https://www.nike.com/t/victori-one-mens-slides-vrTGLL/CN9675-304" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1152px;"><p class="vanilla-image-block" style="padding-top:125.00%;"><img id="Mz3Cjo9qZABfdrYoi3ovNj" name="nike victori one slides" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Mz3Cjo9qZABfdrYoi3ovNj-1920-80.png" mos="" align="middle" fullscreen="" width="1152" height="1440" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nike.com/t/victori-one-mens-slides-vrTGLL/CN9675-304" target="_blank" rel="nofollow" data-dimension112="c590e140-ce16-11f1-b8f5-2165faf7167e" data-action="Deal Block" data-label="Victori One Slides (Men's)" data-dimension48="Victori One Slides (Men's)" data-dimension25="$27">Victori One Slides (Men's): was $37 now $27</a></strong><br />These Nike slides are perfect for staying comfy when you're relaxing indoors or out. Right now, you can get a pair for as little as $27, which is a steal. <a class="view-deal button" href="https://www.nike.com/t/victori-one-mens-slides-vrTGLL/CN9675-304" target="_blank" rel="nofollow" data-dimension112="c590e140-ce16-11f1-b8f5-2165faf7167e" data-action="Deal Block" data-label="Victori One Slides (Men's)" data-dimension48="Victori One Slides (Men's)" data-dimension25="$27">View Deal</a></p></div><div class="product"><a data-dimension112="28a4656a-ce1a-11f1-b818-db1a72325cdb" data-action="Deal Block" data-label="Uplift Sc Shoes (Women's)" data-dimension48="Uplift Sc Shoes (Women's)" data-dimension25="$49" href="https://www.amazon.com/Nike-Womens-Uplift-Sneaker-Black/dp/B0F13DYVP8" 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:47.33%;"><img id="zRhg6N5G4meqd9RBtCU5i6" name="Uplift Sc Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zRhg6N5G4meqd9RBtCU5i6-1920-80.jpg" mos="" align="middle" fullscreen="" width="1500" height="710" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nike-Womens-Uplift-Sneaker-Black/dp/B0F13DYVP8" target="_blank" rel="nofollow" data-dimension112="28a4656a-ce1a-11f1-b818-db1a72325cdb" data-action="Deal Block" data-label="Uplift Sc Shoes (Women's)" data-dimension48="Uplift Sc Shoes (Women's)" data-dimension25="$49">Uplift Sc Shoes (Women's): was $70 now $49</a></strong><br />These casual Nike sneakers have a super-soft textile upper and plush foam cushioning that'll support your feet through their toughest journeys. They're well-loved by Amazon shoppers, too, earning a 4.5-star rating based on over 500 reviews.<a class="view-deal button" href="https://www.amazon.com/Nike-Womens-Uplift-Sneaker-Black/dp/B0F13DYVP8" target="_blank" rel="nofollow" data-dimension112="28a4656a-ce1a-11f1-b818-db1a72325cdb" data-action="Deal Block" data-label="Uplift Sc Shoes (Women's)" data-dimension48="Uplift Sc Shoes (Women's)" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="c590e1ae-ce16-11f1-9d2d-df95b6798613" data-action="Deal Block" data-label="Downshifter 14 (Men's)" data-dimension48="Downshifter 14 (Men's)" data-dimension25="$49" href="https://www.nike.com/t/downshifter-14-mens-road-running-shoe-wrouoOtz/IB1895-108" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1070px;"><p class="vanilla-image-block" style="padding-top:125.05%;"><img id="zCmFyZvZvT6Ayijv4yrZGL" name="Downshifter 14 (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zCmFyZvZvT6Ayijv4yrZGL-1920-80.jpg" mos="" align="middle" fullscreen="" width="1070" height="1338" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nike.com/t/downshifter-14-mens-road-running-shoe-wrouoOtz/IB1895-108" target="_blank" rel="nofollow" data-dimension112="c590e1ae-ce16-11f1-9d2d-df95b6798613" data-action="Deal Block" data-label="Downshifter 14 (Men's)" data-dimension48="Downshifter 14 (Men's)" data-dimension25="$49">Downshifter 14 (Men's): was $80 now $49</a></strong><br />The Nike Downshifter 14 are some of the cheapest Nike running shoes around — and this is a popular deal with only a few sizes left in stock! These road running shoes have a lightweight and breathable mesh upper, improved support thanks to their internal fit band and a soft foam midsole.<a class="view-deal button" href="https://www.nike.com/t/downshifter-14-mens-road-running-shoe-wrouoOtz/IB1895-108" target="_blank" rel="nofollow" data-dimension112="c590e1ae-ce16-11f1-9d2d-df95b6798613" data-action="Deal Block" data-label="Downshifter 14 (Men's)" data-dimension48="Downshifter 14 (Men's)" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="c590e28a-ce16-11f1-b830-09f3362655c9" data-action="Deal Block" data-label="Revolution 8 Road Running Shoes (Women's)" data-dimension48="Revolution 8 Road Running Shoes (Women's)" data-dimension25="$52" href="https://www.amazon.com/Nike-Revolution-Running-White-Particle-Rose-Tattoo/dp/B0DPHRJLX1" 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:47.73%;"><img id="mgvruyyzCcNL6RT2MW9d86" name="Revolution 8 Road Running Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/mgvruyyzCcNL6RT2MW9d86-1920-80.jpg" mos="" align="middle" fullscreen="" width="1500" height="716" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nike-Revolution-Running-White-Particle-Rose-Tattoo/dp/B0DPHRJLX1" target="_blank" rel="nofollow" data-dimension112="c590e28a-ce16-11f1-b830-09f3362655c9" data-action="Deal Block" data-label="Revolution 8 Road Running Shoes (Women's)" data-dimension48="Revolution 8 Road Running Shoes (Women's)" data-dimension25="$52">Revolution 8 Road Running Shoes (Women's): was $70 now $52</a></strong><br />These Nike road runners are on sale starting from just $52, which is a steal. They're packed with cushioning, have a breathable mesh upper and a flexible outsole. <a class="view-deal button" href="https://www.amazon.com/Nike-Revolution-Running-White-Particle-Rose-Tattoo/dp/B0DPHRJLX1" target="_blank" rel="nofollow" data-dimension112="c590e28a-ce16-11f1-b830-09f3362655c9" data-action="Deal Block" data-label="Revolution 8 Road Running Shoes (Women's)" data-dimension48="Revolution 8 Road Running Shoes (Women's)" data-dimension25="$52">View Deal</a></p></div><div class="product"><a data-dimension112="c590e21c-ce16-11f1-87a3-972487cad230" data-action="Deal Block" data-label="Flex Train Workout Shoes (Men's)" data-dimension48="Flex Train Workout Shoes (Men's)" data-dimension25="$59" href="https://www.amazon.com/Nike-Train-Sneaker-Safety-Orange/dp/B0FBS23WGF" 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:41.73%;"><img id="r7FRkdByzV8oBkZ6N2AJj8" name="Flex Train Workout Shoes (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/r7FRkdByzV8oBkZ6N2AJj8-1920-80.jpg" mos="" align="middle" fullscreen="" width="1500" height="626" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nike-Train-Sneaker-Safety-Orange/dp/B0FBS23WGF" target="_blank" rel="nofollow" data-dimension112="c590e21c-ce16-11f1-87a3-972487cad230" data-action="Deal Block" data-label="Flex Train Workout Shoes (Men's)" data-dimension48="Flex Train Workout Shoes (Men's)" data-dimension25="$59">Flex Train Workout Shoes (Men's): was $80 now $59</a></strong><br />Great for a variety of workouts, the Nike Flex Train are a steal with prices starting from $59. These are designed to be extra lightweight and flexible, with comfortable cushioning along the entire midsole. They also look pretty excellent. <a class="view-deal button" href="https://www.amazon.com/Nike-Train-Sneaker-Safety-Orange/dp/B0FBS23WGF" target="_blank" rel="nofollow" data-dimension112="c590e21c-ce16-11f1-87a3-972487cad230" data-action="Deal Block" data-label="Flex Train Workout Shoes (Men's)" data-dimension48="Flex Train Workout Shoes (Men's)" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="c590e2f8-ce16-11f1-9abb-fdb00f6f4e11" data-action="Deal Block" data-label="Flex Control 4 (Men's)" data-dimension48="Flex Control 4 (Men's)" data-dimension25="$59" href="https://www.nike.com/t/flex-control-4-mens-workout-shoes-14Z62l/CD0197-002" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1152px;"><p class="vanilla-image-block" style="padding-top:125.00%;"><img id="scsYMxY2qNypF4Mx8uThT4" name="nike flex control 4" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/scsYMxY2qNypF4Mx8uThT4-1920-80.png" mos="" align="middle" fullscreen="" width="1152" height="1440" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nike.com/t/flex-control-4-mens-workout-shoes-14Z62l/CD0197-002" target="_blank" rel="nofollow" data-dimension112="c590e2f8-ce16-11f1-9abb-fdb00f6f4e11" data-action="Deal Block" data-label="Flex Control 4 (Men's)" data-dimension48="Flex Control 4 (Men's)" data-dimension25="$59">Flex Control 4 (Men's): was $70 now $59</a></strong><br />The Nike Flex Control 4 can now be yours for just $59. These budget-friendly sneakers are designed for workouts, with flexible soles and a midfoot strap to keep them securely on your feet.<a class="view-deal button" href="https://www.nike.com/t/flex-control-4-mens-workout-shoes-14Z62l/CD0197-002" target="_blank" rel="nofollow" data-dimension112="c590e2f8-ce16-11f1-9abb-fdb00f6f4e11" data-action="Deal Block" data-label="Flex Control 4 (Men's)" data-dimension48="Flex Control 4 (Men's)" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="c590e3d4-ce16-11f1-b721-87623cdab7f0" data-action="Deal Block" data-label="Air Monarch IV Training/Workout Shoes (Men's)" data-dimension48="Air Monarch IV Training/Workout Shoes (Men's)" data-dimension25="$59" href="https://www.amazon.com/Monarch-Training-Shoes-Metallic-Silver-Mid/dp/B004IM3JO0" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1611px;"><p class="vanilla-image-block" style="padding-top:50.03%;"><img id="WvCxU4cK4R2aacLaDQGyLN" name="Air Monarch IV Training/Workout Shoes (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/WvCxU4cK4R2aacLaDQGyLN-1920-80.jpg" mos="" align="middle" fullscreen="" width="1611" height="806" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Monarch-Training-Shoes-Metallic-Silver-Mid/dp/B004IM3JO0" target="_blank" rel="nofollow" data-dimension112="c590e3d4-ce16-11f1-b721-87623cdab7f0" data-action="Deal Block" data-label="Air Monarch IV Training/Workout Shoes (Men's)" data-dimension48="Air Monarch IV Training/Workout Shoes (Men's)" data-dimension25="$59">Air Monarch IV Training/Workout Shoes (Men's): was $85 now $59</a></strong><br />Enhance your training sessions in the gym with the Nike Air Monarch IV. They're durable, lightweight and supportive — and beloved by shoppers on Amazon, with one reviewer writing "Great comfort, cushioning, long-wearing and a great value." <a class="view-deal button" href="https://www.amazon.com/Monarch-Training-Shoes-Metallic-Silver-Mid/dp/B004IM3JO0" target="_blank" rel="nofollow" data-dimension112="c590e3d4-ce16-11f1-b721-87623cdab7f0" data-action="Deal Block" data-label="Air Monarch IV Training/Workout Shoes (Men's)" data-dimension48="Air Monarch IV Training/Workout Shoes (Men's)" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="c590e366-ce16-11f1-afc1-3502e4696026" data-action="Deal Block" data-label="Court Shot Herrenschuh Sneakers (Men's)" data-dimension48="Court Shot Herrenschuh Sneakers (Men's)" data-dimension25="$63" href="https://www.amazon.com/Nike-Court-Shoes-Sneaker-Black/dp/B0F1325R84" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1608px;"><p class="vanilla-image-block" style="padding-top:40.80%;"><img id="pDtAyY4zxyRycE74uP7eue" name="Court Shot Herrenschuh Sneakers (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pDtAyY4zxyRycE74uP7eue-1920-80.jpg" mos="" align="middle" fullscreen="" width="1608" height="656" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nike-Court-Shoes-Sneaker-Black/dp/B0F1325R84" target="_blank" rel="nofollow" data-dimension112="c590e366-ce16-11f1-afc1-3502e4696026" data-action="Deal Block" data-label="Court Shot Herrenschuh Sneakers (Men's)" data-dimension48="Court Shot Herrenschuh Sneakers (Men's)" data-dimension25="$63">Court Shot Herrenschuh Sneakers (Men's): was $80 now $63</a></strong><br />The Nike Court Shot Herrenschuh have a super sleek look and are perfect for elevated outfits that still look cool and casual. They have a synthetic leather upper and padded collar for a super comfortable feel. <a class="view-deal button" href="https://www.amazon.com/Nike-Court-Shoes-Sneaker-Black/dp/B0F1325R84" target="_blank" rel="nofollow" data-dimension112="c590e366-ce16-11f1-afc1-3502e4696026" data-action="Deal Block" data-label="Court Shot Herrenschuh Sneakers (Men's)" data-dimension48="Court Shot Herrenschuh Sneakers (Men's)" data-dimension25="$63">View Deal</a></p></div><div class="product"><a data-dimension112="c590e442-ce16-11f1-8f4d-2dc64e641d86" data-action="Deal Block" data-label="Run Swift 3 (Women's)" data-dimension48="Run Swift 3 (Women's)" data-dimension25="$65" href="https://www.amazon.com/Nike-Swift-Running-Shoes-Spruce-Sanddrift-Sail/dp/B0BX4B1S1T" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1723px;"><p class="vanilla-image-block" style="padding-top:47.42%;"><img id="oGEcMPMyVERhdD6die3fdA" name="Run Swift" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/oGEcMPMyVERhdD6die3fdA-1920-80.jpg" mos="" align="middle" fullscreen="" width="1723" height="817" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nike-Swift-Running-Shoes-Spruce-Sanddrift-Sail/dp/B0BX4B1S1T" target="_blank" rel="nofollow" data-dimension112="c590e442-ce16-11f1-8f4d-2dc64e641d86" data-action="Deal Block" data-label="Run Swift 3 (Women's)" data-dimension48="Run Swift 3 (Women's)" data-dimension25="$65">Run Swift 3 (Women's): was $85 now $65</a></strong><br />Save on the nifty Swift 3 road running shoes, which feature a durable, comfortable design and soft foam cushioning to give you plenty of support. Breathable mesh keeps air moving through with every stride, and the grippy grooves on the outsole combine flexibility with sure-footed security.<a class="view-deal button" href="https://www.amazon.com/Nike-Swift-Running-Shoes-Spruce-Sanddrift-Sail/dp/B0BX4B1S1T" target="_blank" rel="nofollow" data-dimension112="c590e442-ce16-11f1-8f4d-2dc64e641d86" data-action="Deal Block" data-label="Run Swift 3 (Women's)" data-dimension48="Run Swift 3 (Women's)" data-dimension25="$65">View Deal</a></p></div><div class="product"><a data-dimension112="28a4668c-ce1a-11f1-b29a-6326411c74db" data-action="Deal Block" data-label="Air Max Excee Shoes (Men's)" data-dimension48="Air Max Excee Shoes (Men's)" data-dimension25="$70" href="https://www.amazon.com/dp/B07T7WG4FZ?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1769px;"><p class="vanilla-image-block" style="padding-top:42.68%;"><img id="DfwCdBPWwrLSD4ywzkVkd5" name="Air Max Excee Shoes (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/DfwCdBPWwrLSD4ywzkVkd5-1920-80.jpg" mos="" align="middle" fullscreen="" width="1769" height="755" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B07T7WG4FZ?" target="_blank" rel="nofollow" data-dimension112="28a4668c-ce1a-11f1-b29a-6326411c74db" data-action="Deal Block" data-label="Air Max Excee Shoes (Men's)" data-dimension48="Air Max Excee Shoes (Men's)" data-dimension25="$70">Air Max Excee Shoes (Men's): was $100 now $70</a></strong><br />A comfortable and reliable shoe, the Nike Air Max Excee is now on sale for $70. The style puts a modern twist on the original Air Max shoes, with patches of contrasting textures across the upper.<a class="view-deal button" href="https://www.amazon.com/dp/B07T7WG4FZ?" target="_blank" rel="nofollow" data-dimension112="28a4668c-ce1a-11f1-b29a-6326411c74db" data-action="Deal Block" data-label="Air Max Excee Shoes (Men's)" data-dimension48="Air Max Excee Shoes (Men's)" data-dimension25="$70">View Deal</a></p></div><div class="product"><a data-dimension112="c590e51e-ce16-11f1-9a7f-91aad85e50c1" data-action="Deal Block" data-label="Pegasus 42 (Men's)" data-dimension48="Pegasus 42 (Men's)" data-dimension25="$82" href="https://www.nike.com/t/pegasus-42-mens-road-running-shoes-S1bYkOza/IB1873-107" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1070px;"><p class="vanilla-image-block" style="padding-top:125.05%;"><img id="uxG2rhW9L4NBaWbeVEreNS" name="Nike Pegasus 42" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/uxG2rhW9L4NBaWbeVEreNS-1920-80.png" mos="" align="middle" fullscreen="" width="1070" height="1338" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nike.com/t/pegasus-42-mens-road-running-shoes-S1bYkOza/IB1873-107" target="_blank" rel="nofollow" data-dimension112="c590e51e-ce16-11f1-9a7f-91aad85e50c1" data-action="Deal Block" data-label="Pegasus 42 (Men's)" data-dimension48="Pegasus 42 (Men's)" data-dimension25="$82">Pegasus 42 (Men's): was $145 now $82</a></strong><br />Earning a 3.5-star rating in our <a href="https://www.tomsguide.com/wellness/running/nike-pegasus-42-review">Nike Pegasus 42 review</a>, we currently rank this as one of the <a href="https://www.tomsguide.com/best-picks/best-running-shoes">best running shoes</a> you can buy in terms of value. Compared to the Pegasus 41 (which was already great,) the 42 feels even smoother and more energetic underfoot. It's a great shoe for just about anybody.<a class="view-deal button" href="https://www.nike.com/t/pegasus-42-mens-road-running-shoes-S1bYkOza/IB1873-107" target="_blank" rel="nofollow" data-dimension112="c590e51e-ce16-11f1-9a7f-91aad85e50c1" data-action="Deal Block" data-label="Pegasus 42 (Men's)" data-dimension48="Pegasus 42 (Men's)" data-dimension25="$82">View Deal</a></p></div><div class="product"><a data-dimension112="def7095c-cef2-11f1-9d02-4bdf0ba83225" data-action="Deal Block" data-label="V5 RNR" data-dimension48="V5 RNR" data-dimension25="$85" href="https://www.amazon.com/Nike-Womens-Sneaker-Metallic-Silver/dp/B0FBHZFS9L" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1070px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="JYFv7uRx28KgqsJ4Gf3iga" name="Nike V5 RNR" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/JYFv7uRx28KgqsJ4Gf3iga-1920-80.jpg" mos="" align="middle" fullscreen="" width="1070" height="1070" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>Tackle the everyday in a shoe that matches comfort with style. Staying true to its Y2K roots, the V5 RNR has a foam midsole that's chunky yet lightweight. Plus, metallic details and a 3D Swoosh logo elevate this retro runner.<a class="view-deal button" href="https://www.amazon.com/Nike-Womens-Sneaker-Metallic-Silver/dp/B0FBHZFS9L" target="_blank" rel="nofollow" data-dimension112="def7095c-cef2-11f1-9d02-4bdf0ba83225" data-action="Deal Block" data-label="V5 RNR" data-dimension48="V5 RNR" data-dimension25="$85">View Deal</a></p></div><div class="product"><a data-dimension112="def709d4-cef2-11f1-8238-27d3bcb8e882" data-action="Deal Block" data-label="Journey Run Road Running Shoes (Men's)" data-dimension48="Journey Run Road Running Shoes (Men's)" data-dimension25="$85" href="https://www.amazon.com/Nike-Journey-Running-FN0228-001-Anthracite/dp/B0D2DJ5Z58" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1070px;"><p class="vanilla-image-block" style="padding-top:125.05%;"><img id="4xXdT6m9HxzUUo9qTuvaBV" name="Journey Run (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4xXdT6m9HxzUUo9qTuvaBV-1920-80.jpg" mos="" align="middle" fullscreen="" width="1070" height="1338" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nike-Journey-Running-FN0228-001-Anthracite/dp/B0D2DJ5Z58" target="_blank" rel="nofollow" data-dimension112="def709d4-cef2-11f1-8238-27d3bcb8e882" data-action="Deal Block" data-label="Journey Run Road Running Shoes (Men's)" data-dimension48="Journey Run Road Running Shoes (Men's)" data-dimension25="$85">Journey Run Road Running Shoes (Men's): was $95 now $85</a></strong><br />Relish every step of the journey with the Nike Journey Run road running shoes, which were designed to pound the pavement with aplomb. You get plenty of cushioning under the heel to keep you bouncy right up until the last mile, with soft touch points in the tongue and collar to keep chafing at bay.<a class="view-deal button" href="https://www.amazon.com/Nike-Journey-Running-FN0228-001-Anthracite/dp/B0D2DJ5Z58" target="_blank" rel="nofollow" data-dimension112="def709d4-cef2-11f1-8238-27d3bcb8e882" data-action="Deal Block" data-label="Journey Run Road Running Shoes (Men's)" data-dimension48="Journey Run Road Running Shoes (Men's)" data-dimension25="$85">View Deal</a></p></div><div class="product"><a data-dimension112="c590e4b0-ce16-11f1-81fe-11e9a1a49e23" data-action="Deal Block" data-label="Pegasus 41 Running Shoes (Women's)" data-dimension48="Pegasus 41 Running Shoes (Women's)" data-dimension25="$106" href="https://www.amazon.com/Nike-Pegasus-Sneaker-Playful-Metallic/dp/B0F2G75S6N" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:44.60%;"><img id="8rtJszfW7dGEJYJc4He9CN" name="81O2j-efNTL._AC_SX695_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/8rtJszfW7dGEJYJc4He9CN-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="310" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nike-Pegasus-Sneaker-Playful-Metallic/dp/B0F2G75S6N" target="_blank" rel="nofollow" data-dimension112="c590e4b0-ce16-11f1-81fe-11e9a1a49e23" data-action="Deal Block" data-label="Pegasus 41 Running Shoes (Women's)" data-dimension48="Pegasus 41 Running Shoes (Women's)" data-dimension25="$106">Pegasus 41 Running Shoes (Women's): was $140 now $106</a></strong><br />The ReactX midsole and higher stack on the Pegasus 41 give it a softer ride than its predecessors, but it’s not so squishy underfoot as to be unstable in any way. It’s a balanced midsole that is comfortable for easy and long runs, but has a little bounce to it when you want to up the pace. Read our full <a href="https://www.tomsguide.com/wellness/running/i-ran-35-miles-in-the-nike-pegasus-41-and-its-my-favorite-pegasus-in-years">Nike Pegasus 41 review</a> here to find out more.<a class="view-deal button" href="https://www.amazon.com/Nike-Pegasus-Sneaker-Playful-Metallic/dp/B0F2G75S6N" target="_blank" rel="nofollow" data-dimension112="c590e4b0-ce16-11f1-81fe-11e9a1a49e23" data-action="Deal Block" data-label="Pegasus 41 Running Shoes (Women's)" data-dimension48="Pegasus 41 Running Shoes (Women's)" data-dimension25="$106">View Deal</a></p></div><div class="product"><a data-dimension112="c590e5c8-ce16-11f1-a28c-3ff67766a372" data-action="Deal Block" data-label="Structure Plus (Men's)" data-dimension48="Structure Plus (Men's)" data-dimension25="$118" href="https://www.nike.com/t/structure-plus-mens-road-running-shoes-XEfeTqfe/IR1816-100" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1070px;"><p class="vanilla-image-block" style="padding-top:125.05%;"><img id="AsCNB6yFLQbuH7JwdNFcpf" name="Nike Structure Plus" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/AsCNB6yFLQbuH7JwdNFcpf-1920-80.png" mos="" align="middle" fullscreen="" width="1070" height="1338" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nike.com/t/structure-plus-mens-road-running-shoes-XEfeTqfe/IR1816-100" target="_blank" rel="nofollow" data-dimension112="c590e5c8-ce16-11f1-a28c-3ff67766a372" data-action="Deal Block" data-label="Structure Plus (Men's)" data-dimension48="Structure Plus (Men's)" data-dimension25="$118">Structure Plus (Men's): was $180 now $118</a></strong><br />The<a href="https://www.tomsguide.com/wellness/running/i-ran-35-miles-in-the-nike-structure-plus-heres-my-verdict-on-nikes-most-cushioned-stability-shoe"> Nike Structure Plus </a>is a stability running shoe that provides a lot of support as well as comfort. Our tester enjoyed racking up the miles in this shoe, which is bouncier than most traditional stability shoes thanks to the ZoomX foam in its midsole.<a class="view-deal button" href="https://www.nike.com/t/structure-plus-mens-road-running-shoes-XEfeTqfe/IR1816-100" target="_blank" rel="nofollow" data-dimension112="c590e5c8-ce16-11f1-a28c-3ff67766a372" data-action="Deal Block" data-label="Structure Plus (Men's)" data-dimension48="Structure Plus (Men's)" data-dimension25="$118">View Deal</a></p></div><div class="product"><a data-dimension112="c590e6d6-ce16-11f1-9ec6-c9cddc54e6e6" data-action="Deal Block" data-label="Zoom Fly 6 (Men's)" data-dimension48="Zoom Fly 6 (Men's)" data-dimension25="$143" href="https://www.nike.com/t/zoom-fly-6-mens-road-racing-shoes-wn2ALjkm/IV6296-635" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1070px;"><p class="vanilla-image-block" style="padding-top:125.05%;"><img id="nqSnCnJGciuR9s63xgLepK" name="Nike Zoom Fly 6" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/nqSnCnJGciuR9s63xgLepK-1920-80.png" mos="" align="middle" fullscreen="" width="1070" height="1338" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nike.com/t/zoom-fly-6-mens-road-racing-shoes-wn2ALjkm/IV6296-635" target="_blank" rel="nofollow" data-dimension112="c590e6d6-ce16-11f1-9ec6-c9cddc54e6e6" data-action="Deal Block" data-label="Zoom Fly 6 (Men's)" data-dimension48="Zoom Fly 6 (Men's)" data-dimension25="$143">Zoom Fly 6 (Men's): was $190 now $143</a></strong><br />The <a href="https://www.tomsguide.com/wellness/running/nike-zoom-fly-6-review">Nike Zoom Fly 6</a> is a ‘super-trainer’, which is a type of shoe that uses some of the tech from the <a href="https://www.tomsguide.com/best-picks/best-carbon-fiber-running-shoes">best carbon plate running shoes</a> in a sneaker that’s cheaper and more suitable for daily training, rather than just being good for race day.<a class="view-deal button" href="https://www.nike.com/t/zoom-fly-6-mens-road-racing-shoes-wn2ALjkm/IV6296-635" target="_blank" rel="nofollow" data-dimension112="c590e6d6-ce16-11f1-9ec6-c9cddc54e6e6" data-action="Deal Block" data-label="Zoom Fly 6 (Men's)" data-dimension48="Zoom Fly 6 (Men's)" data-dimension25="$143">View Deal</a></p></div><div class="product"><a data-dimension112="c590e78a-ce16-11f1-aaf8-5f4db6b5697f" data-action="Deal Block" data-label="Alphafly 3 (Women's)" data-dimension48="Alphafly 3 (Women's)" data-dimension25="$221" href="https://www.nike.com/t/alphafly-3-womens-road-racing-shoes-LQX5b4/FD8315-700" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1152px;"><p class="vanilla-image-block" style="padding-top:125.00%;"><img id="pTKFtRHQkEja7ovGDvyNob" name="nike alphafly 3" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pTKFtRHQkEja7ovGDvyNob-1920-80.png" mos="" align="middle" fullscreen="" width="1152" height="1440" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nike.com/t/alphafly-3-womens-road-racing-shoes-LQX5b4/FD8315-700" target="_blank" rel="nofollow" data-dimension112="c590e78a-ce16-11f1-aaf8-5f4db6b5697f" data-action="Deal Block" data-label="Alphafly 3 (Women's)" data-dimension48="Alphafly 3 (Women's)" data-dimension25="$221">Alphafly 3 (Women's): was $295 now $221</a></strong><br />You can currently save 25% on the <a href="https://www.tomsguide.com/wellness/running/i-ran-80-miles-in-the-nike-alphafly-3-and-nikes-record-breaking-racing-shoe-didnt-disappoint">Nike Alphafly 3</a>, which we rank as one of the <a href="https://www.tomsguide.com/best-picks/best-carbon-fiber-running-shoes">best carbon plate running shoes</a>. These are an awesome pick for runners looking to set fast times thanks to their lightweight, propulsive design.<a class="view-deal button" href="https://www.nike.com/t/alphafly-3-womens-road-racing-shoes-LQX5b4/FD8315-700" target="_blank" rel="nofollow" data-dimension112="c590e78a-ce16-11f1-aaf8-5f4db6b5697f" data-action="Deal Block" data-label="Alphafly 3 (Women's)" data-dimension48="Alphafly 3 (Women's)" data-dimension25="$221">View Deal</a></p></div><div data-model-name="Nike Men's Pegasus 41 Road Running Shoe" data-widget-type="review"></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/running/we-named-the-nike-pegasus-42-the-best-value-running-shoe-on-the-market-and-its-42-percent-off-right-now-plus-15-more-of-our-favorite-nike-running-shoe-deals</link>
                                                                            <description>
                            <![CDATA[ The best Nike running shoes we've tested, the Nike Pegasus 42, just got a major price cut. Check out the biggest savings right now! ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">iw6bdv3m6dMBMwenhNpiAd</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/RiUcAVwxuZTXqWJaygGgN8-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 22 Oct 2026 13:37:45 +0000</pubDate>                                                                                                                                <updated>Fri, 23 Oct 2026 15:03:14 +0000</updated>
                                                                                                                                            <category><![CDATA[Running]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                                                                <author><![CDATA[ millie.daviswilliams@futurenet.com (Millie Davis-Williams) ]]></author>                    <dc:creator><![CDATA[ Millie Davis-Williams ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/WU6pa7hKuxs5ScCoqcXYWA-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Millie is a Deals Editor at Tom&#039;s Guide specializing in tech deals content. Based in London, Millie has spent a lifetime stubbornly refusing to pay full price on any possible purchase. She has years of searching for the best discounts on the latest and greatest phones, TVs and gadgets under her belt, and knows how to sort the best deals from the rest. Helping readers save on the products they want is her mission, whether it’s an Apple Watch or a new tablet.&lt;/p&gt;&lt;p&gt;Since working at Tom’s Guide, Millie has covered retail events like Prime Day, Black Friday and Cyber Monday extensively, meaning she knows the products readers are looking for and the best times of year to hit “purchase.”&lt;/p&gt;&lt;p&gt;When she’s not looking for discounts, Millie covers news and writes how-to articles about everything from phones, streaming devices, and headphones to apps and video games.&lt;/p&gt;&lt;p&gt;In her spare time, Millie enjoys reading, gaming on her Nintendo Switch and creating digital art. She’s also a fan of watching Disney movies and collecting plush (the latter having totally taken over her bedroom.)&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/RiUcAVwxuZTXqWJaygGgN8-1920-80.jpg">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Nike Pegasus 42 running shoes]]></media:description>                                                            <media:text><![CDATA[Nike Pegasus 42 running shoes]]></media:text>
                                <media:title type="plain"><![CDATA[Nike Pegasus 42 running shoes]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/RiUcAVwxuZTXqWJaygGgN8-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>It's a great day to buy a new pair of running shoes — even if your wallet is feeling the pinch. Don't hang around, the <a href="https://www.tomsguide.com/best-picks/best-running-shoes">best value running shoes</a> we've tested just got a big price cut!</p><p>The <a href="https://www.nike.com/t/pegasus-42-mens-road-running-shoes-S1bYkOza/IB1873-107" target="_blank" rel="nofollow">Nike Pegasus 42 are on sale from $82 at Nike</a>. These were already excellent value at full price, and with 42% off (a fitting discount for the 42nd version of the shoe) they're an absolute steal. They're versatile, smooth and great for both beginners and experienced runners alike.</p><p><strong>Note: </strong>prices vary depending on the size and color you choose. To find the best deals, check out any different color options available in your size. For more, see our <a href="https://www.tomsguide.com/wellness/fitness/nike-promo-codes">Nike promo codes</a>.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><a href="https://www.amazon.com/stores/page/E9C7C6A6-9A88-4959-A67F-4D44FC67320F" target="_blank" rel="nofollow"><strong>shop Nike deals at Amazon</strong></a><strong></strong></li><li><strong>Nike Victori One Slides (Men's): </strong><a href="https://www.nike.com/t/victori-one-mens-slides-vrTGLL/CN9675-304" target="_blank" rel="nofollow"><strong>was $37 now from $27</strong></a></li><li><strong>Nike Uplift Sc Shoes (Women's): </strong><a href="https://www.amazon.com/Nike-Womens-Uplift-Sneaker-Black/dp/B0F13DYVP8" target="_blank" rel="nofollow"><strong>was $70 now from $49</strong></a></li><li><strong>Nike Downshifter 14 (Men's): </strong><a href="https://www.nike.com/t/downshifter-14-mens-road-running-shoe-wrouoOtz/IB1895-108" target="_blank" rel="nofollow"><strong>was $80 now from $49</strong></a></li><li><strong>Nike Flex Train Workout Shoes (Men's): </strong><a href="https://www.amazon.com/Nike-Train-Sneaker-Safety-Orange/dp/B0FBS23WGF" target="_blank" rel="nofollow"><strong>was $80 now from $59</strong></a></li><li><strong>Nike Pegasus 42 (Men's): </strong><a href="https://www.nike.com/t/pegasus-42-mens-road-running-shoes-S1bYkOza/IB1873-107" target="_blank" rel="nofollow"><strong>was $145 now from $82</strong></a><br /><strong>Nike Zoom Fly 6 (Men's): </strong><a href="https://www.nike.com/t/zoom-fly-6-mens-road-racing-shoes-wn2ALjkm/IV6296-635" target="_blank" rel="nofollow"><strong>was $190 now from $143</strong></a></li><li><strong>Nike Alphafly 3 (Women's): </strong><a href="https://www.nike.com/t/alphafly-3-womens-road-racing-shoes-LQX5b4" target="_blank" rel="nofollow"><strong>was $295 now from $221</strong></a></li></ul><h3 class="article-body__section" id="section-nike-footwear-deals"><span>Nike Footwear Deals</span></h3><div class="product"><a data-dimension112="c590e140-ce16-11f1-b8f5-2165faf7167e" data-action="Deal Block" data-label="Victori One Slides (Men's)" data-dimension48="Victori One Slides (Men's)" data-dimension25="$27" href="https://www.nike.com/t/victori-one-mens-slides-vrTGLL/CN9675-304" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1152px;"><p class="vanilla-image-block" style="padding-top:125.00%;"><img id="Mz3Cjo9qZABfdrYoi3ovNj" name="nike victori one slides" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Mz3Cjo9qZABfdrYoi3ovNj-1920-80.png" mos="" align="middle" fullscreen="" width="1152" height="1440" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nike.com/t/victori-one-mens-slides-vrTGLL/CN9675-304" target="_blank" rel="nofollow" data-dimension112="c590e140-ce16-11f1-b8f5-2165faf7167e" data-action="Deal Block" data-label="Victori One Slides (Men's)" data-dimension48="Victori One Slides (Men's)" data-dimension25="$27">Victori One Slides (Men's): was $37 now $27</a></strong><br />These Nike slides are perfect for staying comfy when you're relaxing indoors or out. Right now, you can get a pair for as little as $27, which is a steal. <a class="view-deal button" href="https://www.nike.com/t/victori-one-mens-slides-vrTGLL/CN9675-304" target="_blank" rel="nofollow" data-dimension112="c590e140-ce16-11f1-b8f5-2165faf7167e" data-action="Deal Block" data-label="Victori One Slides (Men's)" data-dimension48="Victori One Slides (Men's)" data-dimension25="$27">View Deal</a></p></div><div class="product"><a data-dimension112="28a4656a-ce1a-11f1-b818-db1a72325cdb" data-action="Deal Block" data-label="Uplift Sc Shoes (Women's)" data-dimension48="Uplift Sc Shoes (Women's)" data-dimension25="$49" href="https://www.amazon.com/Nike-Womens-Uplift-Sneaker-Black/dp/B0F13DYVP8" 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:47.33%;"><img id="zRhg6N5G4meqd9RBtCU5i6" name="Uplift Sc Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zRhg6N5G4meqd9RBtCU5i6-1920-80.jpg" mos="" align="middle" fullscreen="" width="1500" height="710" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nike-Womens-Uplift-Sneaker-Black/dp/B0F13DYVP8" target="_blank" rel="nofollow" data-dimension112="28a4656a-ce1a-11f1-b818-db1a72325cdb" data-action="Deal Block" data-label="Uplift Sc Shoes (Women's)" data-dimension48="Uplift Sc Shoes (Women's)" data-dimension25="$49">Uplift Sc Shoes (Women's): was $70 now $49</a></strong><br />These casual Nike sneakers have a super-soft textile upper and plush foam cushioning that'll support your feet through their toughest journeys. They're well-loved by Amazon shoppers, too, earning a 4.5-star rating based on over 500 reviews.<a class="view-deal button" href="https://www.amazon.com/Nike-Womens-Uplift-Sneaker-Black/dp/B0F13DYVP8" target="_blank" rel="nofollow" data-dimension112="28a4656a-ce1a-11f1-b818-db1a72325cdb" data-action="Deal Block" data-label="Uplift Sc Shoes (Women's)" data-dimension48="Uplift Sc Shoes (Women's)" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="c590e1ae-ce16-11f1-9d2d-df95b6798613" data-action="Deal Block" data-label="Downshifter 14 (Men's)" data-dimension48="Downshifter 14 (Men's)" data-dimension25="$49" href="https://www.nike.com/t/downshifter-14-mens-road-running-shoe-wrouoOtz/IB1895-108" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1070px;"><p class="vanilla-image-block" style="padding-top:125.05%;"><img id="zCmFyZvZvT6Ayijv4yrZGL" name="Downshifter 14 (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zCmFyZvZvT6Ayijv4yrZGL-1920-80.jpg" mos="" align="middle" fullscreen="" width="1070" height="1338" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nike.com/t/downshifter-14-mens-road-running-shoe-wrouoOtz/IB1895-108" target="_blank" rel="nofollow" data-dimension112="c590e1ae-ce16-11f1-9d2d-df95b6798613" data-action="Deal Block" data-label="Downshifter 14 (Men's)" data-dimension48="Downshifter 14 (Men's)" data-dimension25="$49">Downshifter 14 (Men's): was $80 now $49</a></strong><br />The Nike Downshifter 14 are some of the cheapest Nike running shoes around — and this is a popular deal with only a few sizes left in stock! These road running shoes have a lightweight and breathable mesh upper, improved support thanks to their internal fit band and a soft foam midsole.<a class="view-deal button" href="https://www.nike.com/t/downshifter-14-mens-road-running-shoe-wrouoOtz/IB1895-108" target="_blank" rel="nofollow" data-dimension112="c590e1ae-ce16-11f1-9d2d-df95b6798613" data-action="Deal Block" data-label="Downshifter 14 (Men's)" data-dimension48="Downshifter 14 (Men's)" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="c590e28a-ce16-11f1-b830-09f3362655c9" data-action="Deal Block" data-label="Revolution 8 Road Running Shoes (Women's)" data-dimension48="Revolution 8 Road Running Shoes (Women's)" data-dimension25="$52" href="https://www.amazon.com/Nike-Revolution-Running-White-Particle-Rose-Tattoo/dp/B0DPHRJLX1" 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:47.73%;"><img id="mgvruyyzCcNL6RT2MW9d86" name="Revolution 8 Road Running Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/mgvruyyzCcNL6RT2MW9d86-1920-80.jpg" mos="" align="middle" fullscreen="" width="1500" height="716" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nike-Revolution-Running-White-Particle-Rose-Tattoo/dp/B0DPHRJLX1" target="_blank" rel="nofollow" data-dimension112="c590e28a-ce16-11f1-b830-09f3362655c9" data-action="Deal Block" data-label="Revolution 8 Road Running Shoes (Women's)" data-dimension48="Revolution 8 Road Running Shoes (Women's)" data-dimension25="$52">Revolution 8 Road Running Shoes (Women's): was $70 now $52</a></strong><br />These Nike road runners are on sale starting from just $52, which is a steal. They're packed with cushioning, have a breathable mesh upper and a flexible outsole. <a class="view-deal button" href="https://www.amazon.com/Nike-Revolution-Running-White-Particle-Rose-Tattoo/dp/B0DPHRJLX1" target="_blank" rel="nofollow" data-dimension112="c590e28a-ce16-11f1-b830-09f3362655c9" data-action="Deal Block" data-label="Revolution 8 Road Running Shoes (Women's)" data-dimension48="Revolution 8 Road Running Shoes (Women's)" data-dimension25="$52">View Deal</a></p></div><div class="product"><a data-dimension112="c590e21c-ce16-11f1-87a3-972487cad230" data-action="Deal Block" data-label="Flex Train Workout Shoes (Men's)" data-dimension48="Flex Train Workout Shoes (Men's)" data-dimension25="$59" href="https://www.amazon.com/Nike-Train-Sneaker-Safety-Orange/dp/B0FBS23WGF" 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:41.73%;"><img id="r7FRkdByzV8oBkZ6N2AJj8" name="Flex Train Workout Shoes (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/r7FRkdByzV8oBkZ6N2AJj8-1920-80.jpg" mos="" align="middle" fullscreen="" width="1500" height="626" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nike-Train-Sneaker-Safety-Orange/dp/B0FBS23WGF" target="_blank" rel="nofollow" data-dimension112="c590e21c-ce16-11f1-87a3-972487cad230" data-action="Deal Block" data-label="Flex Train Workout Shoes (Men's)" data-dimension48="Flex Train Workout Shoes (Men's)" data-dimension25="$59">Flex Train Workout Shoes (Men's): was $80 now $59</a></strong><br />Great for a variety of workouts, the Nike Flex Train are a steal with prices starting from $59. These are designed to be extra lightweight and flexible, with comfortable cushioning along the entire midsole. They also look pretty excellent. <a class="view-deal button" href="https://www.amazon.com/Nike-Train-Sneaker-Safety-Orange/dp/B0FBS23WGF" target="_blank" rel="nofollow" data-dimension112="c590e21c-ce16-11f1-87a3-972487cad230" data-action="Deal Block" data-label="Flex Train Workout Shoes (Men's)" data-dimension48="Flex Train Workout Shoes (Men's)" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="c590e2f8-ce16-11f1-9abb-fdb00f6f4e11" data-action="Deal Block" data-label="Flex Control 4 (Men's)" data-dimension48="Flex Control 4 (Men's)" data-dimension25="$59" href="https://www.nike.com/t/flex-control-4-mens-workout-shoes-14Z62l/CD0197-002" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1152px;"><p class="vanilla-image-block" style="padding-top:125.00%;"><img id="scsYMxY2qNypF4Mx8uThT4" name="nike flex control 4" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/scsYMxY2qNypF4Mx8uThT4-1920-80.png" mos="" align="middle" fullscreen="" width="1152" height="1440" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nike.com/t/flex-control-4-mens-workout-shoes-14Z62l/CD0197-002" target="_blank" rel="nofollow" data-dimension112="c590e2f8-ce16-11f1-9abb-fdb00f6f4e11" data-action="Deal Block" data-label="Flex Control 4 (Men's)" data-dimension48="Flex Control 4 (Men's)" data-dimension25="$59">Flex Control 4 (Men's): was $70 now $59</a></strong><br />The Nike Flex Control 4 can now be yours for just $59. These budget-friendly sneakers are designed for workouts, with flexible soles and a midfoot strap to keep them securely on your feet.<a class="view-deal button" href="https://www.nike.com/t/flex-control-4-mens-workout-shoes-14Z62l/CD0197-002" target="_blank" rel="nofollow" data-dimension112="c590e2f8-ce16-11f1-9abb-fdb00f6f4e11" data-action="Deal Block" data-label="Flex Control 4 (Men's)" data-dimension48="Flex Control 4 (Men's)" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="c590e3d4-ce16-11f1-b721-87623cdab7f0" data-action="Deal Block" data-label="Air Monarch IV Training/Workout Shoes (Men's)" data-dimension48="Air Monarch IV Training/Workout Shoes (Men's)" data-dimension25="$59" href="https://www.amazon.com/Monarch-Training-Shoes-Metallic-Silver-Mid/dp/B004IM3JO0" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1611px;"><p class="vanilla-image-block" style="padding-top:50.03%;"><img id="WvCxU4cK4R2aacLaDQGyLN" name="Air Monarch IV Training/Workout Shoes (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/WvCxU4cK4R2aacLaDQGyLN-1920-80.jpg" mos="" align="middle" fullscreen="" width="1611" height="806" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Monarch-Training-Shoes-Metallic-Silver-Mid/dp/B004IM3JO0" target="_blank" rel="nofollow" data-dimension112="c590e3d4-ce16-11f1-b721-87623cdab7f0" data-action="Deal Block" data-label="Air Monarch IV Training/Workout Shoes (Men's)" data-dimension48="Air Monarch IV Training/Workout Shoes (Men's)" data-dimension25="$59">Air Monarch IV Training/Workout Shoes (Men's): was $85 now $59</a></strong><br />Enhance your training sessions in the gym with the Nike Air Monarch IV. They're durable, lightweight and supportive — and beloved by shoppers on Amazon, with one reviewer writing "Great comfort, cushioning, long-wearing and a great value." <a class="view-deal button" href="https://www.amazon.com/Monarch-Training-Shoes-Metallic-Silver-Mid/dp/B004IM3JO0" target="_blank" rel="nofollow" data-dimension112="c590e3d4-ce16-11f1-b721-87623cdab7f0" data-action="Deal Block" data-label="Air Monarch IV Training/Workout Shoes (Men's)" data-dimension48="Air Monarch IV Training/Workout Shoes (Men's)" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="c590e366-ce16-11f1-afc1-3502e4696026" data-action="Deal Block" data-label="Court Shot Herrenschuh Sneakers (Men's)" data-dimension48="Court Shot Herrenschuh Sneakers (Men's)" data-dimension25="$63" href="https://www.amazon.com/Nike-Court-Shoes-Sneaker-Black/dp/B0F1325R84" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1608px;"><p class="vanilla-image-block" style="padding-top:40.80%;"><img id="pDtAyY4zxyRycE74uP7eue" name="Court Shot Herrenschuh Sneakers (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pDtAyY4zxyRycE74uP7eue-1920-80.jpg" mos="" align="middle" fullscreen="" width="1608" height="656" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nike-Court-Shoes-Sneaker-Black/dp/B0F1325R84" target="_blank" rel="nofollow" data-dimension112="c590e366-ce16-11f1-afc1-3502e4696026" data-action="Deal Block" data-label="Court Shot Herrenschuh Sneakers (Men's)" data-dimension48="Court Shot Herrenschuh Sneakers (Men's)" data-dimension25="$63">Court Shot Herrenschuh Sneakers (Men's): was $80 now $63</a></strong><br />The Nike Court Shot Herrenschuh have a super sleek look and are perfect for elevated outfits that still look cool and casual. They have a synthetic leather upper and padded collar for a super comfortable feel. <a class="view-deal button" href="https://www.amazon.com/Nike-Court-Shoes-Sneaker-Black/dp/B0F1325R84" target="_blank" rel="nofollow" data-dimension112="c590e366-ce16-11f1-afc1-3502e4696026" data-action="Deal Block" data-label="Court Shot Herrenschuh Sneakers (Men's)" data-dimension48="Court Shot Herrenschuh Sneakers (Men's)" data-dimension25="$63">View Deal</a></p></div><div class="product"><a data-dimension112="c590e442-ce16-11f1-8f4d-2dc64e641d86" data-action="Deal Block" data-label="Run Swift 3 (Women's)" data-dimension48="Run Swift 3 (Women's)" data-dimension25="$65" href="https://www.amazon.com/Nike-Swift-Running-Shoes-Spruce-Sanddrift-Sail/dp/B0BX4B1S1T" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1723px;"><p class="vanilla-image-block" style="padding-top:47.42%;"><img id="oGEcMPMyVERhdD6die3fdA" name="Run Swift" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/oGEcMPMyVERhdD6die3fdA-1920-80.jpg" mos="" align="middle" fullscreen="" width="1723" height="817" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nike-Swift-Running-Shoes-Spruce-Sanddrift-Sail/dp/B0BX4B1S1T" target="_blank" rel="nofollow" data-dimension112="c590e442-ce16-11f1-8f4d-2dc64e641d86" data-action="Deal Block" data-label="Run Swift 3 (Women's)" data-dimension48="Run Swift 3 (Women's)" data-dimension25="$65">Run Swift 3 (Women's): was $85 now $65</a></strong><br />Save on the nifty Swift 3 road running shoes, which feature a durable, comfortable design and soft foam cushioning to give you plenty of support. Breathable mesh keeps air moving through with every stride, and the grippy grooves on the outsole combine flexibility with sure-footed security.<a class="view-deal button" href="https://www.amazon.com/Nike-Swift-Running-Shoes-Spruce-Sanddrift-Sail/dp/B0BX4B1S1T" target="_blank" rel="nofollow" data-dimension112="c590e442-ce16-11f1-8f4d-2dc64e641d86" data-action="Deal Block" data-label="Run Swift 3 (Women's)" data-dimension48="Run Swift 3 (Women's)" data-dimension25="$65">View Deal</a></p></div><div class="product"><a data-dimension112="28a4668c-ce1a-11f1-b29a-6326411c74db" data-action="Deal Block" data-label="Air Max Excee Shoes (Men's)" data-dimension48="Air Max Excee Shoes (Men's)" data-dimension25="$70" href="https://www.amazon.com/dp/B07T7WG4FZ?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1769px;"><p class="vanilla-image-block" style="padding-top:42.68%;"><img id="DfwCdBPWwrLSD4ywzkVkd5" name="Air Max Excee Shoes (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/DfwCdBPWwrLSD4ywzkVkd5-1920-80.jpg" mos="" align="middle" fullscreen="" width="1769" height="755" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B07T7WG4FZ?" target="_blank" rel="nofollow" data-dimension112="28a4668c-ce1a-11f1-b29a-6326411c74db" data-action="Deal Block" data-label="Air Max Excee Shoes (Men's)" data-dimension48="Air Max Excee Shoes (Men's)" data-dimension25="$70">Air Max Excee Shoes (Men's): was $100 now $70</a></strong><br />A comfortable and reliable shoe, the Nike Air Max Excee is now on sale for $70. The style puts a modern twist on the original Air Max shoes, with patches of contrasting textures across the upper.<a class="view-deal button" href="https://www.amazon.com/dp/B07T7WG4FZ?" target="_blank" rel="nofollow" data-dimension112="28a4668c-ce1a-11f1-b29a-6326411c74db" data-action="Deal Block" data-label="Air Max Excee Shoes (Men's)" data-dimension48="Air Max Excee Shoes (Men's)" data-dimension25="$70">View Deal</a></p></div><div class="product"><a data-dimension112="c590e51e-ce16-11f1-9a7f-91aad85e50c1" data-action="Deal Block" data-label="Pegasus 42 (Men's)" data-dimension48="Pegasus 42 (Men's)" data-dimension25="$82" href="https://www.nike.com/t/pegasus-42-mens-road-running-shoes-S1bYkOza/IB1873-107" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1070px;"><p class="vanilla-image-block" style="padding-top:125.05%;"><img id="uxG2rhW9L4NBaWbeVEreNS" name="Nike Pegasus 42" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/uxG2rhW9L4NBaWbeVEreNS-1920-80.png" mos="" align="middle" fullscreen="" width="1070" height="1338" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nike.com/t/pegasus-42-mens-road-running-shoes-S1bYkOza/IB1873-107" target="_blank" rel="nofollow" data-dimension112="c590e51e-ce16-11f1-9a7f-91aad85e50c1" data-action="Deal Block" data-label="Pegasus 42 (Men's)" data-dimension48="Pegasus 42 (Men's)" data-dimension25="$82">Pegasus 42 (Men's): was $145 now $82</a></strong><br />Earning a 3.5-star rating in our <a href="https://www.tomsguide.com/wellness/running/nike-pegasus-42-review">Nike Pegasus 42 review</a>, we currently rank this as one of the <a href="https://www.tomsguide.com/best-picks/best-running-shoes">best running shoes</a> you can buy in terms of value. Compared to the Pegasus 41 (which was already great,) the 42 feels even smoother and more energetic underfoot. It's a great shoe for just about anybody.<a class="view-deal button" href="https://www.nike.com/t/pegasus-42-mens-road-running-shoes-S1bYkOza/IB1873-107" target="_blank" rel="nofollow" data-dimension112="c590e51e-ce16-11f1-9a7f-91aad85e50c1" data-action="Deal Block" data-label="Pegasus 42 (Men's)" data-dimension48="Pegasus 42 (Men's)" data-dimension25="$82">View Deal</a></p></div><div class="product"><a data-dimension112="def7095c-cef2-11f1-9d02-4bdf0ba83225" data-action="Deal Block" data-label="V5 RNR" data-dimension48="V5 RNR" data-dimension25="$85" href="https://www.amazon.com/Nike-Womens-Sneaker-Metallic-Silver/dp/B0FBHZFS9L" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1070px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="JYFv7uRx28KgqsJ4Gf3iga" name="Nike V5 RNR" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/JYFv7uRx28KgqsJ4Gf3iga-1920-80.jpg" mos="" align="middle" fullscreen="" width="1070" height="1070" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>Tackle the everyday in a shoe that matches comfort with style. Staying true to its Y2K roots, the V5 RNR has a foam midsole that's chunky yet lightweight. Plus, metallic details and a 3D Swoosh logo elevate this retro runner.<a class="view-deal button" href="https://www.amazon.com/Nike-Womens-Sneaker-Metallic-Silver/dp/B0FBHZFS9L" target="_blank" rel="nofollow" data-dimension112="def7095c-cef2-11f1-9d02-4bdf0ba83225" data-action="Deal Block" data-label="V5 RNR" data-dimension48="V5 RNR" data-dimension25="$85">View Deal</a></p></div><div class="product"><a data-dimension112="def709d4-cef2-11f1-8238-27d3bcb8e882" data-action="Deal Block" data-label="Journey Run Road Running Shoes (Men's)" data-dimension48="Journey Run Road Running Shoes (Men's)" data-dimension25="$85" href="https://www.amazon.com/Nike-Journey-Running-FN0228-001-Anthracite/dp/B0D2DJ5Z58" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1070px;"><p class="vanilla-image-block" style="padding-top:125.05%;"><img id="4xXdT6m9HxzUUo9qTuvaBV" name="Journey Run (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4xXdT6m9HxzUUo9qTuvaBV-1920-80.jpg" mos="" align="middle" fullscreen="" width="1070" height="1338" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nike-Journey-Running-FN0228-001-Anthracite/dp/B0D2DJ5Z58" target="_blank" rel="nofollow" data-dimension112="def709d4-cef2-11f1-8238-27d3bcb8e882" data-action="Deal Block" data-label="Journey Run Road Running Shoes (Men's)" data-dimension48="Journey Run Road Running Shoes (Men's)" data-dimension25="$85">Journey Run Road Running Shoes (Men's): was $95 now $85</a></strong><br />Relish every step of the journey with the Nike Journey Run road running shoes, which were designed to pound the pavement with aplomb. You get plenty of cushioning under the heel to keep you bouncy right up until the last mile, with soft touch points in the tongue and collar to keep chafing at bay.<a class="view-deal button" href="https://www.amazon.com/Nike-Journey-Running-FN0228-001-Anthracite/dp/B0D2DJ5Z58" target="_blank" rel="nofollow" data-dimension112="def709d4-cef2-11f1-8238-27d3bcb8e882" data-action="Deal Block" data-label="Journey Run Road Running Shoes (Men's)" data-dimension48="Journey Run Road Running Shoes (Men's)" data-dimension25="$85">View Deal</a></p></div><div class="product"><a data-dimension112="c590e4b0-ce16-11f1-81fe-11e9a1a49e23" data-action="Deal Block" data-label="Pegasus 41 Running Shoes (Women's)" data-dimension48="Pegasus 41 Running Shoes (Women's)" data-dimension25="$106" href="https://www.amazon.com/Nike-Pegasus-Sneaker-Playful-Metallic/dp/B0F2G75S6N" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:44.60%;"><img id="8rtJszfW7dGEJYJc4He9CN" name="81O2j-efNTL._AC_SX695_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/8rtJszfW7dGEJYJc4He9CN-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="310" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Nike-Pegasus-Sneaker-Playful-Metallic/dp/B0F2G75S6N" target="_blank" rel="nofollow" data-dimension112="c590e4b0-ce16-11f1-81fe-11e9a1a49e23" data-action="Deal Block" data-label="Pegasus 41 Running Shoes (Women's)" data-dimension48="Pegasus 41 Running Shoes (Women's)" data-dimension25="$106">Pegasus 41 Running Shoes (Women's): was $140 now $106</a></strong><br />The ReactX midsole and higher stack on the Pegasus 41 give it a softer ride than its predecessors, but it’s not so squishy underfoot as to be unstable in any way. It’s a balanced midsole that is comfortable for easy and long runs, but has a little bounce to it when you want to up the pace. Read our full <a href="https://www.tomsguide.com/wellness/running/i-ran-35-miles-in-the-nike-pegasus-41-and-its-my-favorite-pegasus-in-years">Nike Pegasus 41 review</a> here to find out more.<a class="view-deal button" href="https://www.amazon.com/Nike-Pegasus-Sneaker-Playful-Metallic/dp/B0F2G75S6N" target="_blank" rel="nofollow" data-dimension112="c590e4b0-ce16-11f1-81fe-11e9a1a49e23" data-action="Deal Block" data-label="Pegasus 41 Running Shoes (Women's)" data-dimension48="Pegasus 41 Running Shoes (Women's)" data-dimension25="$106">View Deal</a></p></div><div class="product"><a data-dimension112="c590e5c8-ce16-11f1-a28c-3ff67766a372" data-action="Deal Block" data-label="Structure Plus (Men's)" data-dimension48="Structure Plus (Men's)" data-dimension25="$118" href="https://www.nike.com/t/structure-plus-mens-road-running-shoes-XEfeTqfe/IR1816-100" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1070px;"><p class="vanilla-image-block" style="padding-top:125.05%;"><img id="AsCNB6yFLQbuH7JwdNFcpf" name="Nike Structure Plus" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/AsCNB6yFLQbuH7JwdNFcpf-1920-80.png" mos="" align="middle" fullscreen="" width="1070" height="1338" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nike.com/t/structure-plus-mens-road-running-shoes-XEfeTqfe/IR1816-100" target="_blank" rel="nofollow" data-dimension112="c590e5c8-ce16-11f1-a28c-3ff67766a372" data-action="Deal Block" data-label="Structure Plus (Men's)" data-dimension48="Structure Plus (Men's)" data-dimension25="$118">Structure Plus (Men's): was $180 now $118</a></strong><br />The<a href="https://www.tomsguide.com/wellness/running/i-ran-35-miles-in-the-nike-structure-plus-heres-my-verdict-on-nikes-most-cushioned-stability-shoe"> Nike Structure Plus </a>is a stability running shoe that provides a lot of support as well as comfort. Our tester enjoyed racking up the miles in this shoe, which is bouncier than most traditional stability shoes thanks to the ZoomX foam in its midsole.<a class="view-deal button" href="https://www.nike.com/t/structure-plus-mens-road-running-shoes-XEfeTqfe/IR1816-100" target="_blank" rel="nofollow" data-dimension112="c590e5c8-ce16-11f1-a28c-3ff67766a372" data-action="Deal Block" data-label="Structure Plus (Men's)" data-dimension48="Structure Plus (Men's)" data-dimension25="$118">View Deal</a></p></div><div class="product"><a data-dimension112="c590e6d6-ce16-11f1-9ec6-c9cddc54e6e6" data-action="Deal Block" data-label="Zoom Fly 6 (Men's)" data-dimension48="Zoom Fly 6 (Men's)" data-dimension25="$143" href="https://www.nike.com/t/zoom-fly-6-mens-road-racing-shoes-wn2ALjkm/IV6296-635" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1070px;"><p class="vanilla-image-block" style="padding-top:125.05%;"><img id="nqSnCnJGciuR9s63xgLepK" name="Nike Zoom Fly 6" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/nqSnCnJGciuR9s63xgLepK-1920-80.png" mos="" align="middle" fullscreen="" width="1070" height="1338" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nike.com/t/zoom-fly-6-mens-road-racing-shoes-wn2ALjkm/IV6296-635" target="_blank" rel="nofollow" data-dimension112="c590e6d6-ce16-11f1-9ec6-c9cddc54e6e6" data-action="Deal Block" data-label="Zoom Fly 6 (Men's)" data-dimension48="Zoom Fly 6 (Men's)" data-dimension25="$143">Zoom Fly 6 (Men's): was $190 now $143</a></strong><br />The <a href="https://www.tomsguide.com/wellness/running/nike-zoom-fly-6-review">Nike Zoom Fly 6</a> is a ‘super-trainer’, which is a type of shoe that uses some of the tech from the <a href="https://www.tomsguide.com/best-picks/best-carbon-fiber-running-shoes">best carbon plate running shoes</a> in a sneaker that’s cheaper and more suitable for daily training, rather than just being good for race day.<a class="view-deal button" href="https://www.nike.com/t/zoom-fly-6-mens-road-racing-shoes-wn2ALjkm/IV6296-635" target="_blank" rel="nofollow" data-dimension112="c590e6d6-ce16-11f1-9ec6-c9cddc54e6e6" data-action="Deal Block" data-label="Zoom Fly 6 (Men's)" data-dimension48="Zoom Fly 6 (Men's)" data-dimension25="$143">View Deal</a></p></div><div class="product"><a data-dimension112="c590e78a-ce16-11f1-aaf8-5f4db6b5697f" data-action="Deal Block" data-label="Alphafly 3 (Women's)" data-dimension48="Alphafly 3 (Women's)" data-dimension25="$221" href="https://www.nike.com/t/alphafly-3-womens-road-racing-shoes-LQX5b4/FD8315-700" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1152px;"><p class="vanilla-image-block" style="padding-top:125.00%;"><img id="pTKFtRHQkEja7ovGDvyNob" name="nike alphafly 3" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pTKFtRHQkEja7ovGDvyNob-1920-80.png" mos="" align="middle" fullscreen="" width="1152" height="1440" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nike.com/t/alphafly-3-womens-road-racing-shoes-LQX5b4/FD8315-700" target="_blank" rel="nofollow" data-dimension112="c590e78a-ce16-11f1-aaf8-5f4db6b5697f" data-action="Deal Block" data-label="Alphafly 3 (Women's)" data-dimension48="Alphafly 3 (Women's)" data-dimension25="$221">Alphafly 3 (Women's): was $295 now $221</a></strong><br />You can currently save 25% on the <a href="https://www.tomsguide.com/wellness/running/i-ran-80-miles-in-the-nike-alphafly-3-and-nikes-record-breaking-racing-shoe-didnt-disappoint">Nike Alphafly 3</a>, which we rank as one of the <a href="https://www.tomsguide.com/best-picks/best-carbon-fiber-running-shoes">best carbon plate running shoes</a>. These are an awesome pick for runners looking to set fast times thanks to their lightweight, propulsive design.<a class="view-deal button" href="https://www.nike.com/t/alphafly-3-womens-road-racing-shoes-LQX5b4/FD8315-700" target="_blank" rel="nofollow" data-dimension112="c590e78a-ce16-11f1-aaf8-5f4db6b5697f" data-action="Deal Block" data-label="Alphafly 3 (Women's)" data-dimension48="Alphafly 3 (Women's)" data-dimension25="$221">View Deal</a></p></div><div data-model-name="Nike Men's Pegasus 41 Road Running Shoe" data-widget-type="review"></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ My 50-year-old client wanted to start lifting weights at home — these are the 4 dumbbell exercises I gave her first ]]></title>
                                                                                                <dc:content><![CDATA[ <p>You don't need a fancy, expensive gym membership to build muscle and strength. Sure, you might have more equipment available at a gym, but you can do a lot more than you may realize with just a set of <a href="https://www.tomsguide.com/wellness/fitness/best-adjustable-dumbbells">adjustable dumbbells</a> or even a medium-heavy set of fixed dumbbells and your exercise mat.</p><p>Most importantly, you need to focus on three key areas with your workouts: <strong>consistency</strong> (several times per week, if you can), <strong>staple functional </strong><a href="https://www.tomsguide.com/wellness/fitness/im-a-personal-trainer-these-are-the-5-compound-exercises-i-taught-my-dad-to-build-strength-and-muscle"><strong>compound exercises</strong></a><strong> </strong>and <strong>progressive programming. </strong>That means repeating exercises and tweaking them to feel more challenging over time while focusing on multiple muscle groups. Do that, and it doesn't matter if you're at home or in the studio.</p><p>Not long ago, my 50-year-old client asked for a home dumbbell workout she could do between sessions. These are the four moves and the routine I gave her. Just remember, this routine was designed with someone in mind. If you experience pain or feel unwell, stop immediately and seek medical advice as soon as possible.</p><h2 id="watch-20-minute-dumbbell-workout">Watch: 20-minute dumbbell workout</h2><p><em>If you're working with an injury or health condition, I recommend seeking advice before starting this routine.</em></p><ul><li><strong>Curtsy lunges: 3-4 sets of 6-8 heavy reps per side.</strong></li><li>Start with your feet hip-width apart, weights at your sides or one weight held at your chest. Step your right foot out to the side on your toes, then circle the right foot back behind your left in a wide arc over to the left. Imagine you're drawing a smiley face. Bend your knees and lower into a lunge, hinging forward slightly at the hips with a straight back. It should look like you're curtsying. Drive up through your legs and core to stand, then repeat the lunge. Switch sides after you complete your reps.</li></ul><iframe src="https://content.jwplatform.com/players/tQ98ST0x.html" id="tQ98ST0x" title="Project Move - Curtsy Lunge" width="960" height="540" frameborder="0" scrolling="auto" allowfullscreen=""></iframe><ul><li><strong>Thrusters</strong>: <strong>3-4 sets of 8-10 reps.</strong></li><li>Stand with your feet roughly shoulder-width apart and rack your dumbbells to your shoulders, elbows drawn upward for support. Brace your core. Sit your hips back and squat, sitting as low as you can while pressing through your feet. Your chest should be proud, back straight. Drive upward to stand and press the weights overhead in one move. Keep your arms close to your ears to stabilize the weights. As you sit back into the squat, bring the weights back to your shoulders.</li></ul><iframe src="https://content.jwplatform.com/players/3fBuTsyk.html" id="3fBuTsyk" title="Project Move - Thrusters" width="960" height="540" frameborder="0" scrolling="auto" allowfullscreen=""></iframe><ul><li><strong>Suitcase deadlifts:</strong> <strong>3-4 sets of 8-10 reps.</strong></li><li>Stand holding your weights at your sides, feet hip-width apart and core active. Set your shoulders back and down, then slowly hinge forward at your hips, maintaining a soft knee bend. Keep your chest proud and back straight. Lower the weights along your outer legs toward the ground. If you can reach the ground outside your feet without hunching, great; if not, pause near the ground, then press upward to stand with power.</li></ul><iframe src="https://content.jwplatform.com/players/r57z5PbE.html" id="r57z5PbE" title="Project Move - Suitcase Deadlift" width="960" height="540" frameborder="0" scrolling="auto" allowfullscreen=""></iframe><ul><li><strong>Alternating rows: 3-4 sets of 6-8 heavy reps per side.</strong></li><li>Hinge forward at your hips until your chest is almost parallel to the ground, feet hip-width apart and core engaged. Hold your weights with a neutral grip in front of your shins. With control, row one weight toward your back pocket, elbow nice and close to your body. Pause, squeeze your back, then lower the weight again. Repeat on the other side.</li></ul><iframe src="https://content.jwplatform.com/players/1Do7LJ9j.html" id="1Do7LJ9j" title="Project Move - Alternating Row" width="960" height="540" frameborder="0" scrolling="auto" allowfullscreen=""></iframe><h2 id="what-are-the-benefits-2">What are the benefits?</h2><div><blockquote><p>You're hitting pretty much every major muscle group during this routine</p></blockquote></div><p>You're hitting pretty much every major muscle group during this routine; <strong>curtsy lunges </strong>strengthen your legs with an outer gluteus and adductor bias, meaning your butt and inner thighs will feel this one; <strong>thrusters</strong> work the whole body, including your legs, glutes, core, triceps, shoulders and upper chest; <strong>suitcase deadlifts</strong> work your posterior chain, including your lower back, glutes and hamstrings, but the position of the weights will also strengthen your quads and knees, and your core works hard for stability; finally, <strong>rows</strong> hit your back and biceps, meaning better posture and pulling power while improving your hip hinge.</p><p>I like to load quite heavy on these exercises, but make sure your form doesn't get put to one side for the sake of load. A general rule of thumb: aim for the last two or three reps to be difficult to finish, but not impossible. Lifting close to failure with intensity is one of the <a href="https://www.tomsguide.com/features/5-clever-ways-to-build-muscle-without-lifting-heavy">best ways to build muscle </a>and make gains with your routine. </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><p>Take 30-60 seconds of rest between your sets and move with control. You could also try slowing the tempo of each move to increase overall intensity. </p><p>My client rates this routine for working her whole body while remaining low-impact and easy to scale up or down. She's moved up in weight a few times since we first programmed it, and credits it with helping her build and maintain muscle and strength between her gym sessions. Plus, she doesn't have to leave the house. Bonus!</p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="vGnNDN" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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><strong></strong><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"><strong>I teach people how to be more mobile: 3 low-impact back and shoulder moves that build stability and strength after 40</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-how-to-be-strong-and-mobile-this-is-the-one-exercise-i-regret-ignoring-for-years" target="_blank"><strong>I teach people how to be strong and mobile: this is the one exercise I regret ignoring for years</strong></a><strong></strong></li><li><strong></strong><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"><strong>I teach people over 50 to be mobile: 3 low-impact moves that build more stability than a 30-minute walk</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/workouts/my-50-year-old-client-wanted-to-start-lifting-weights-at-home-these-are-the-4-dumbbell-exercises-i-gave-her-first</link>
                                                                            <description>
                            <![CDATA[ Try this 20-minute dumbbell workout for a full-body burn at home with one set of weights. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">DCV94y2sqW34MQVdj25FN7</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/GqBJRADbSUyK5DaQt7pw9g-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Thu, 22 Oct 2026 09:30:00 +0000</pubDate>                                                                                                                                <updated>Thu, 22 Oct 2026 17:28:36 +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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/GqBJRADbSUyK5DaQt7pw9g-1920-80.jpg">
                                                            <media:credit><![CDATA[Getty Images]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a woman performing dumbbell curls]]></media:description>                                                            <media:text><![CDATA[a woman performing dumbbell curls]]></media:text>
                                <media:title type="plain"><![CDATA[a woman performing dumbbell curls]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/GqBJRADbSUyK5DaQt7pw9g-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>You don't need a fancy, expensive gym membership to build muscle and strength. Sure, you might have more equipment available at a gym, but you can do a lot more than you may realize with just a set of <a href="https://www.tomsguide.com/wellness/fitness/best-adjustable-dumbbells">adjustable dumbbells</a> or even a medium-heavy set of fixed dumbbells and your exercise mat.</p><p>Most importantly, you need to focus on three key areas with your workouts: <strong>consistency</strong> (several times per week, if you can), <strong>staple functional </strong><a href="https://www.tomsguide.com/wellness/fitness/im-a-personal-trainer-these-are-the-5-compound-exercises-i-taught-my-dad-to-build-strength-and-muscle"><strong>compound exercises</strong></a><strong> </strong>and <strong>progressive programming. </strong>That means repeating exercises and tweaking them to feel more challenging over time while focusing on multiple muscle groups. Do that, and it doesn't matter if you're at home or in the studio.</p><p>Not long ago, my 50-year-old client asked for a home dumbbell workout she could do between sessions. These are the four moves and the routine I gave her. Just remember, this routine was designed with someone in mind. If you experience pain or feel unwell, stop immediately and seek medical advice as soon as possible.</p><h2 id="watch-20-minute-dumbbell-workout">Watch: 20-minute dumbbell workout</h2><p><em>If you're working with an injury or health condition, I recommend seeking advice before starting this routine.</em></p><ul><li><strong>Curtsy lunges: 3-4 sets of 6-8 heavy reps per side.</strong></li><li>Start with your feet hip-width apart, weights at your sides or one weight held at your chest. Step your right foot out to the side on your toes, then circle the right foot back behind your left in a wide arc over to the left. Imagine you're drawing a smiley face. Bend your knees and lower into a lunge, hinging forward slightly at the hips with a straight back. It should look like you're curtsying. Drive up through your legs and core to stand, then repeat the lunge. Switch sides after you complete your reps.</li></ul><iframe src="https://content.jwplatform.com/players/tQ98ST0x.html" id="tQ98ST0x" title="Project Move - Curtsy Lunge" width="960" height="540" frameborder="0" scrolling="auto" allowfullscreen=""></iframe><ul><li><strong>Thrusters</strong>: <strong>3-4 sets of 8-10 reps.</strong></li><li>Stand with your feet roughly shoulder-width apart and rack your dumbbells to your shoulders, elbows drawn upward for support. Brace your core. Sit your hips back and squat, sitting as low as you can while pressing through your feet. Your chest should be proud, back straight. Drive upward to stand and press the weights overhead in one move. Keep your arms close to your ears to stabilize the weights. As you sit back into the squat, bring the weights back to your shoulders.</li></ul><iframe src="https://content.jwplatform.com/players/3fBuTsyk.html" id="3fBuTsyk" title="Project Move - Thrusters" width="960" height="540" frameborder="0" scrolling="auto" allowfullscreen=""></iframe><ul><li><strong>Suitcase deadlifts:</strong> <strong>3-4 sets of 8-10 reps.</strong></li><li>Stand holding your weights at your sides, feet hip-width apart and core active. Set your shoulders back and down, then slowly hinge forward at your hips, maintaining a soft knee bend. Keep your chest proud and back straight. Lower the weights along your outer legs toward the ground. If you can reach the ground outside your feet without hunching, great; if not, pause near the ground, then press upward to stand with power.</li></ul><iframe src="https://content.jwplatform.com/players/r57z5PbE.html" id="r57z5PbE" title="Project Move - Suitcase Deadlift" width="960" height="540" frameborder="0" scrolling="auto" allowfullscreen=""></iframe><ul><li><strong>Alternating rows: 3-4 sets of 6-8 heavy reps per side.</strong></li><li>Hinge forward at your hips until your chest is almost parallel to the ground, feet hip-width apart and core engaged. Hold your weights with a neutral grip in front of your shins. With control, row one weight toward your back pocket, elbow nice and close to your body. Pause, squeeze your back, then lower the weight again. Repeat on the other side.</li></ul><iframe src="https://content.jwplatform.com/players/1Do7LJ9j.html" id="1Do7LJ9j" title="Project Move - Alternating Row" width="960" height="540" frameborder="0" scrolling="auto" allowfullscreen=""></iframe><h2 id="what-are-the-benefits-2">What are the benefits?</h2><div><blockquote><p>You're hitting pretty much every major muscle group during this routine</p></blockquote></div><p>You're hitting pretty much every major muscle group during this routine; <strong>curtsy lunges </strong>strengthen your legs with an outer gluteus and adductor bias, meaning your butt and inner thighs will feel this one; <strong>thrusters</strong> work the whole body, including your legs, glutes, core, triceps, shoulders and upper chest; <strong>suitcase deadlifts</strong> work your posterior chain, including your lower back, glutes and hamstrings, but the position of the weights will also strengthen your quads and knees, and your core works hard for stability; finally, <strong>rows</strong> hit your back and biceps, meaning better posture and pulling power while improving your hip hinge.</p><p>I like to load quite heavy on these exercises, but make sure your form doesn't get put to one side for the sake of load. A general rule of thumb: aim for the last two or three reps to be difficult to finish, but not impossible. Lifting close to failure with intensity is one of the <a href="https://www.tomsguide.com/features/5-clever-ways-to-build-muscle-without-lifting-heavy">best ways to build muscle </a>and make gains with your routine. </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><p>Take 30-60 seconds of rest between your sets and move with control. You could also try slowing the tempo of each move to increase overall intensity. </p><p>My client rates this routine for working her whole body while remaining low-impact and easy to scale up or down. She's moved up in weight a few times since we first programmed it, and credits it with helping her build and maintain muscle and strength between her gym sessions. Plus, she doesn't have to leave the house. Bonus!</p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="vGnNDN" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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><strong></strong><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"><strong>I teach people how to be more mobile: 3 low-impact back and shoulder moves that build stability and strength after 40</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-how-to-be-strong-and-mobile-this-is-the-one-exercise-i-regret-ignoring-for-years" target="_blank"><strong>I teach people how to be strong and mobile: this is the one exercise I regret ignoring for years</strong></a><strong></strong></li><li><strong></strong><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"><strong>I teach people over 50 to be mobile: 3 low-impact moves that build more stability than a 30-minute walk</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I’ve owned this Patagonia fleece for a decade — it’s perfect for cold mornings and chilly evenings, and it's 50% off right now in this secret sale ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The clocks are changing, the temperature is dropping, and fleece season is officially here. I’ve been testing fitness gear for a decade, and one of my go-to items is my Micro-D Patagonia fleece — and right now, it’s <a href="https://www.rei.com/product/242671/patagonia-micro-d-half-zip-fleece-pullover-womens " target="_blank" rel="nofollow">50% off in this REI sale</a>. </p><p>Good gear lasts more than one season, and this fleece is going into its 10th winter. It has a high neck to keep the weather out, and it’s made of fast-drying microfleece for a breathable yet cosy layer. </p><div class="product"><a data-dimension112="089e506e-cc7b-11f1-b1cd-7313d4eb11ad" data-action="Deal Block" data-label="Micro-D Half-Zip Fleece Pullover" data-dimension48="Micro-D Half-Zip Fleece Pullover" data-dimension25="$48" href="https://www.rei.com/product/242671/patagonia-micro-d-half-zip-fleece-pullover-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1576px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="nf39PweshXkywy2qiMnC8k" name="b28afb8f-ec50-4921-9346-b3269d66e19b" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/nf39PweshXkywy2qiMnC8k-1920-80.jpg" mos="" align="middle" fullscreen="" width="1576" height="1576" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/242671/patagonia-micro-d-half-zip-fleece-pullover-womens" target="_blank" rel="nofollow" data-dimension112="089e506e-cc7b-11f1-b1cd-7313d4eb11ad" data-action="Deal Block" data-label="Micro-D Half-Zip Fleece Pullover" data-dimension48="Micro-D Half-Zip Fleece Pullover" data-dimension25="$48">Micro-D Half-Zip Fleece Pullover: was $99 now $48</a></strong><br />Right now, the beautiful Thin Ice colorway is down to $48 in REI’s mid-season deal. It’s still available in a handful of sizes. The <a href="https://www.rei.com/product/143319/patagonia-micro-d-fleece-pullover-mens%20" target="_blank" rel="nofollow">men’s Micro D Fleece Pullover is still full price at $79</a>, but REI members can get rewards. <a class="view-deal button" href="https://www.rei.com/product/242671/patagonia-micro-d-half-zip-fleece-pullover-womens" target="_blank" rel="nofollow" data-dimension112="089e506e-cc7b-11f1-b1cd-7313d4eb11ad" data-action="Deal Block" data-label="Micro-D Half-Zip Fleece Pullover" data-dimension48="Micro-D Half-Zip Fleece Pullover" data-dimension25="$48">View Deal</a></p></div><p>This layer is seriously cute and cosy for fall, with dropped shoulders for a relaxed fit that sits at hip-height. It’s a lightweight layer, weighing 8.6 ounces, so it won’t take up much space or weight in your pack, and it has a relaxed fit for throwing on mid-hike. </p><p>The half-zip design makes it easy to layer — you can pull the zip right down to make it more breathable as you start walking, or zip it fully to keep the cold out when you stop for a hot chocolate. The elasticated cuffs keep the cold out, but also make it easier to layer this underneath a jacket or wear gloves. </p><p>Like all Patagonia items, it’s built to last, and my Micro D fleece proves this tenfold. I’ve chucked this in my pack, thrown it on after a marathon, and worn it for countless dog walks. It hasn’t pilled or lost its shape, and it’s one I reach for season after season. Plus, for $48, it’s a bargain right now. </p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness/ive-owned-this-patagonia-fleece-for-a-decade-its-perfect-for-cold-mornings-and-chilly-evenings-and-its-50-percent-off-right-now-in-this-secret-sale</link>
                                                                            <description>
                            <![CDATA[ Now is a great time to grab my go-to layer for fall. Trust me, I'm a fitness editor who reviews outdoor gear for a living! ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">hFGATApRbeqiZab74E9WY3</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/2ZXDTq5RfNW2dKiqzSYkZZ-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 21 Oct 2026 11:00:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Fitness]]></category>
                                                    <category><![CDATA[Wellness]]></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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/2ZXDTq5RfNW2dKiqzSYkZZ-1920-80.jpg">
                                                            <media:credit><![CDATA[Patagonia/Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[A photo of a Patagonia fleece ]]></media:description>                                                            <media:text><![CDATA[A photo of a Patagonia fleece ]]></media:text>
                                <media:title type="plain"><![CDATA[A photo of a Patagonia fleece ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/2ZXDTq5RfNW2dKiqzSYkZZ-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The clocks are changing, the temperature is dropping, and fleece season is officially here. I’ve been testing fitness gear for a decade, and one of my go-to items is my Micro-D Patagonia fleece — and right now, it’s <a href="https://www.rei.com/product/242671/patagonia-micro-d-half-zip-fleece-pullover-womens " target="_blank" rel="nofollow">50% off in this REI sale</a>. </p><p>Good gear lasts more than one season, and this fleece is going into its 10th winter. It has a high neck to keep the weather out, and it’s made of fast-drying microfleece for a breathable yet cosy layer. </p><div class="product"><a data-dimension112="089e506e-cc7b-11f1-b1cd-7313d4eb11ad" data-action="Deal Block" data-label="Micro-D Half-Zip Fleece Pullover" data-dimension48="Micro-D Half-Zip Fleece Pullover" data-dimension25="$48" href="https://www.rei.com/product/242671/patagonia-micro-d-half-zip-fleece-pullover-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1576px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="nf39PweshXkywy2qiMnC8k" name="b28afb8f-ec50-4921-9346-b3269d66e19b" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/nf39PweshXkywy2qiMnC8k-1920-80.jpg" mos="" align="middle" fullscreen="" width="1576" height="1576" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/242671/patagonia-micro-d-half-zip-fleece-pullover-womens" target="_blank" rel="nofollow" data-dimension112="089e506e-cc7b-11f1-b1cd-7313d4eb11ad" data-action="Deal Block" data-label="Micro-D Half-Zip Fleece Pullover" data-dimension48="Micro-D Half-Zip Fleece Pullover" data-dimension25="$48">Micro-D Half-Zip Fleece Pullover: was $99 now $48</a></strong><br />Right now, the beautiful Thin Ice colorway is down to $48 in REI’s mid-season deal. It’s still available in a handful of sizes. The <a href="https://www.rei.com/product/143319/patagonia-micro-d-fleece-pullover-mens%20" target="_blank" rel="nofollow">men’s Micro D Fleece Pullover is still full price at $79</a>, but REI members can get rewards. <a class="view-deal button" href="https://www.rei.com/product/242671/patagonia-micro-d-half-zip-fleece-pullover-womens" target="_blank" rel="nofollow" data-dimension112="089e506e-cc7b-11f1-b1cd-7313d4eb11ad" data-action="Deal Block" data-label="Micro-D Half-Zip Fleece Pullover" data-dimension48="Micro-D Half-Zip Fleece Pullover" data-dimension25="$48">View Deal</a></p></div><p>This layer is seriously cute and cosy for fall, with dropped shoulders for a relaxed fit that sits at hip-height. It’s a lightweight layer, weighing 8.6 ounces, so it won’t take up much space or weight in your pack, and it has a relaxed fit for throwing on mid-hike. </p><p>The half-zip design makes it easy to layer — you can pull the zip right down to make it more breathable as you start walking, or zip it fully to keep the cold out when you stop for a hot chocolate. The elasticated cuffs keep the cold out, but also make it easier to layer this underneath a jacket or wear gloves. </p><p>Like all Patagonia items, it’s built to last, and my Micro D fleece proves this tenfold. I’ve chucked this in my pack, thrown it on after a marathon, and worn it for countless dog walks. It hasn’t pilled or lost its shape, and it’s one I reach for season after season. Plus, for $48, it’s a bargain right now. </p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I’m a personal trainer — this is the one mobility exercise everyone in their 50s should do every single day ]]></title>
                                                                                                <dc:content><![CDATA[ <p>I go on and on to anyone who will listen about how important mobility routines are as you get older. Trust me, at 25, many people barely think about mobility; at 35, they consider it; at 55, they really need it; and at 75, they wish they'd started sooner. </p><p>Thankfully, you can rely on<a href="https://www.instagram.com/tomsguidefitness/" target="_blank"> Tom's Guide Fitness</a> to regularly post mobility routines for every age and ability. I'm the resident personal trainer and editor here at TG, and below, I share one of my favorite mobility exercises to coach. </p><p>I would pick this exact exercise to build range of motion, strength, and control, especially if you're finding these aspects of fitness harder to maintain as you age. This typically becomes more noticeable as you hit your 40s and 50s, so let's take a look at how to battle it.</p><h2 id="how-to-do-the-kick-through">How to do the kick through</h2><ul><li>Start in a high runner's lunge with your left foot forward and planted and your back leg extended, resting the ball of your right foot on the ground</li><li>Place your right hand down for support and square your hips</li><li>Brace your core, lift your back leg off the ground and press through your right hand. Bend your right knee and push your leg through and under your body, kicking it out and away from you as you extend your right leg</li><li>Lift your chest, sit your butt close to the floor without touching and pause for a moment, pointing your toes if you can. See if you can keep your left heel planted</li><li>Reverse the movement back to high runner's lunge</li><li><strong>Try 2-3 sets of 6-8 reps per side.</strong></li></ul><h3 class="article-body__section" id="section-why-you-should-try-the-kickthrough"><span>Why you should try the kickthrough</span></h3><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="vGnNDN" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><p>This is one of those exercises that looks fairly simple but, in practice, tests you. You're strengthening your hips and core, working on improving range of motion and control, and, to some extent, your flexibility. There's also an element of stability and balance work as you learn to coordinate and move your left and right sides independently. </p><div><blockquote><p>The kickthrough is surprisingly functional.</p></blockquote></div><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><p>The kickthrough is surprisingly functional as you transition from one pose to the other. If you notice this more in your hips, try to brace through your core more, as this may signal some weakness or tightness in your hips and a lack of core engagement. </p><p>Moreover, practicing this regularly helps stretch the side body and back, which can be useful for back pain. That said, if you are pre- or post-natal, injured, or dealing with a health condition, I strongly recommend seeking clearance before trying this move. </p><p>As you get older, building stronger bones, joints and muscles becomes even more important to help prevent age-related injuries associated with falls or balance. Unilateral movements like this help strengthen both sides of the body, which translates to activities like walking or running, so be sure to include mobility work alongside strength training and low-impact cardio as you age. </p><p>At 35, I've already started prioritizing movements like these, and I do with my clients, too. If you want more moves like this, try these <a href="https://www.tomsguide.com/wellness/workouts/why-strength-coaches-are-making-adults-exercise-like-animals-and-3-primal-must-try-moves">three "primal" animal exercises</a>. </p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/the-caterpillar-walk-is-considered-the-gold-standard-for-lower-body-mobility-and-flexibility-heres-how-to-do-it"><strong>The caterpillar walk is considered the 'gold standard' for lower body mobility and flexibility — here's how to do it</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/im-a-personal-trainer-this-20-minute-walking-workout-fires-up-your-metabolism-and-builds-functional-strength"><strong>Forget running — this 20-minute walking workout fires up your metabolism and builds functional strength</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/i-did-the-frankenstein-walk-to-strengthen-my-hip-flexors-and-build-core-stability-heres-what-happened-after-a-week"><strong>I did the Frankenstein walk to strengthen my hip flexors and build core stability: here’s what happened after a week</strong></a><strong></strong></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/workouts/im-a-personal-trainer-this-is-the-one-mobility-exercise-everyone-in-their-50s-should-do-every-single-day</link>
                                                                            <description>
                            <![CDATA[ A personal trainer shares a mobility exercise she believes everyone over 50 should do regularly. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">HpazXLvyopWs8kt3sx4Vec</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/b38uWkFeTvJwUXYaPVsuaV-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Wed, 21 Oct 2026 05: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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/b38uWkFeTvJwUXYaPVsuaV-1920-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Two women in their 50s smiling back to back in a light airy studio]]></media:description>                                                            <media:text><![CDATA[Two women in their 50s smiling back to back in a light airy studio]]></media:text>
                                <media:title type="plain"><![CDATA[Two women in their 50s smiling back to back in a light airy studio]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/b38uWkFeTvJwUXYaPVsuaV-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I go on and on to anyone who will listen about how important mobility routines are as you get older. Trust me, at 25, many people barely think about mobility; at 35, they consider it; at 55, they really need it; and at 75, they wish they'd started sooner. </p><p>Thankfully, you can rely on<a href="https://www.instagram.com/tomsguidefitness/" target="_blank"> Tom's Guide Fitness</a> to regularly post mobility routines for every age and ability. I'm the resident personal trainer and editor here at TG, and below, I share one of my favorite mobility exercises to coach. </p><p>I would pick this exact exercise to build range of motion, strength, and control, especially if you're finding these aspects of fitness harder to maintain as you age. This typically becomes more noticeable as you hit your 40s and 50s, so let's take a look at how to battle it.</p><h2 id="how-to-do-the-kick-through">How to do the kick through</h2><ul><li>Start in a high runner's lunge with your left foot forward and planted and your back leg extended, resting the ball of your right foot on the ground</li><li>Place your right hand down for support and square your hips</li><li>Brace your core, lift your back leg off the ground and press through your right hand. Bend your right knee and push your leg through and under your body, kicking it out and away from you as you extend your right leg</li><li>Lift your chest, sit your butt close to the floor without touching and pause for a moment, pointing your toes if you can. See if you can keep your left heel planted</li><li>Reverse the movement back to high runner's lunge</li><li><strong>Try 2-3 sets of 6-8 reps per side.</strong></li></ul><h3 class="article-body__section" id="section-why-you-should-try-the-kickthrough"><span>Why you should try the kickthrough</span></h3><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="vGnNDN" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><p>This is one of those exercises that looks fairly simple but, in practice, tests you. You're strengthening your hips and core, working on improving range of motion and control, and, to some extent, your flexibility. There's also an element of stability and balance work as you learn to coordinate and move your left and right sides independently. </p><div><blockquote><p>The kickthrough is surprisingly functional.</p></blockquote></div><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><p>The kickthrough is surprisingly functional as you transition from one pose to the other. If you notice this more in your hips, try to brace through your core more, as this may signal some weakness or tightness in your hips and a lack of core engagement. </p><p>Moreover, practicing this regularly helps stretch the side body and back, which can be useful for back pain. That said, if you are pre- or post-natal, injured, or dealing with a health condition, I strongly recommend seeking clearance before trying this move. </p><p>As you get older, building stronger bones, joints and muscles becomes even more important to help prevent age-related injuries associated with falls or balance. Unilateral movements like this help strengthen both sides of the body, which translates to activities like walking or running, so be sure to include mobility work alongside strength training and low-impact cardio as you age. </p><p>At 35, I've already started prioritizing movements like these, and I do with my clients, too. If you want more moves like this, try these <a href="https://www.tomsguide.com/wellness/workouts/why-strength-coaches-are-making-adults-exercise-like-animals-and-3-primal-must-try-moves">three "primal" animal exercises</a>. </p><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/the-caterpillar-walk-is-considered-the-gold-standard-for-lower-body-mobility-and-flexibility-heres-how-to-do-it"><strong>The caterpillar walk is considered the 'gold standard' for lower body mobility and flexibility — here's how to do it</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/im-a-personal-trainer-this-20-minute-walking-workout-fires-up-your-metabolism-and-builds-functional-strength"><strong>Forget running — this 20-minute walking workout fires up your metabolism and builds functional strength</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/i-did-the-frankenstein-walk-to-strengthen-my-hip-flexors-and-build-core-stability-heres-what-happened-after-a-week"><strong>I did the Frankenstein walk to strengthen my hip flexors and build core stability: here’s what happened after a week</strong></a><strong></strong></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I swapped sit-ups for rowing crunches in my core workouts and found it a much more effective move ]]></title>
                                                                                                <dc:content><![CDATA[ <p>I don’t particularly enjoy doing abs exercises, but I absolutely do value the importance of having a strong core, both to support my main sport of running and just to make everyday movements easier.</p><p>That means I slip a couple of core moves into almost every workout I do. One of those is always the <a href="https://www.tomsguide.com/wellness/fitness/not-sit-ups-or-planks-i-have-tried-almost-every-abs-exercise-going-and-this-is-the-one-i-always-include-in-my-sessions">bicycle crunch</a>, which I find a very quick and effective way to engage and strengthen my whole core.</p><p>The other move I slip into every workout has changed over time — I’ve done leg raises, <a href="https://www.tomsguide.com/wellness/workouts/forget-sit-ups-the-dying-turtle-is-my-new-favorite-core-exercise-heres-how-to-do-it">dying turtles, </a>and sit-ups — but right now my favourite is the rowing crunch.</p><p>This move mimics the motion of rowing as you bring your knees up to meet your chest, and gets the abs burning in no time at all in my experience. </p><p>It’s similar to a V-sit-up with bent knees, and sometimes also gets called the rower, boat crunch, or rowboat crunch. Whatever you call it, it's a move worth knowing about.</p><h3 class="article-body__section" id="section-how-to-do-the-rowing-crunch"><span>How to do the rowing crunch</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:3000px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="T4HLYJ7EjkqMSVMoWWMzo4" name="v-sit_shutterstock_2002641401.jpg" alt="a woman performing a V-Sit" src="https://cdn.mos.cms.futurecdn.net/T4HLYJ7EjkqMSVMoWWMzo4-1920-80.jpg" mos="" align="middle" fullscreen="" width="3000" height="1687" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Getty Images)</span></figcaption></figure><p>You don’t need any equipment to do the rowing crunch, though using one of the best yoga mats will make it more comfortable on hard floors.</p><ol start="1"><li>Sit on the floor and lean back to a 45-degree angle. Bend your knees and lift your feet slightly off the floor. This is your starting position.</li><li>Simultaneously lean back until your back is hovering just above the floor and extend your legs out away from you, while ‘rowing’ with your arms so your hands finish next to your chest.</li><li>Use your core muscles to pull your knees back towards your chest as you raise your torso up to meet your knees.</li></ol><p>You can make the move a little harder by pausing for a beat at the bottom of the exercise, in a hollow-bold hold position, before coming back up. I tend to do a set of 10 rowers straight after doing a set of 20 bicycle crunches as part of a circuit I do three times overall.</p><h2 class="article-body__section" id="section-benefits-of-the-rowing-crunch"><span>Benefits of the rowing crunch</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="sVJ3deaBiQVQ7EUDUrbNDE" name="abs.abs_gettyimages-1492581875" alt="woman's abs on show" src="https://cdn.mos.cms.futurecdn.net/sVJ3deaBiQVQ7EUDUrbNDE-1920-80.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>The rowing crunch blasts both the upper and lower abs as you raise your torso and lift your knees toward your chest at the same time, while your obliques help keep you balanced throughout the move.</p><p>Throughout the exercise, you have to keep your body stable, which engages the deeper core muscles and keeps them engaged the whole time, since you don’t fully release the tension in your midsection at any point during the move.</p><p>They’re challenging for people of all fitness levels, but also approachable because you don’t need any equipment. If you’re struggling to get through a full set of the move, you can do sit-ups and knee tucks to strengthen your core and build up to the rowing crunch.</p><div><blockquote><p>I find that doing the arms movements to mimic rowing, while not essential, does force me to stay in control through the exercise.</p></blockquote></div><p>I find that doing the arm movements to mimic rowing, while not essential, does force me to stay in control through the exercise and move in a smooth manner that keeps the abs engaged more effectively than jerking up and down.</p><p>There are dozens of great crunch variations that do a similar job to the rowing crunch, and if you’re getting comfortable with the move, you could try V-ups as a progression, but I’ve found them to be the ideal addition to my own workout routine alongside the bicycle crunch.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.js" async=""></script><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-to-be-more-mobile-in-their-60s-and-70s-3-low-impact-exercises-you-should-start-with" target="_blank"><strong>I teach people to be more mobile in their 60s and 70s: 3 low-impact exercises you should start with</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness/forget-burpees-the-pilates-burpee-is-beginner-friendly-and-low-impact-and-youll-love-it" target="_blank"><strong>Forget burpees —the 'Pilates burpee' is beginner-friendly and low-impact (and you’ll love it)</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/a-yoga-instructor-says-this-is-the-5-minute-yoga-routine-you-need-for-strong-and-mobile-hips-and-core-muscles" target="_blank"><strong>A yoga instructor says this is the 5-minute yoga routine you need for strong and mobile hips and core muscles</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/workouts/i-swapped-sit-ups-for-rowing-crunches-in-my-core-workouts-and-found-it-a-much-more-effective-move</link>
                                                                            <description>
                            <![CDATA[ The rowing crunch completely replaced sit-ups in my workout routine — here’s why and how to do it. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">oJWecTrZiBZYJm3KWutp2K</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/tMj6bsXtXhHMM4etWCLvGM-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 20 Oct 2026 11:00: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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/tMj6bsXtXhHMM4etWCLvGM-1920-80.jpg">
                                                            <media:credit><![CDATA[Getty images/ Unknown]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Woman performing a v tap exercise with legs in the air with legs extended in front of her arms reaching forward]]></media:description>                                                            <media:text><![CDATA[Woman performing a v tap exercise with legs in the air with legs extended in front of her arms reaching forward]]></media:text>
                                <media:title type="plain"><![CDATA[Woman performing a v tap exercise with legs in the air with legs extended in front of her arms reaching forward]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/tMj6bsXtXhHMM4etWCLvGM-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>I don’t particularly enjoy doing abs exercises, but I absolutely do value the importance of having a strong core, both to support my main sport of running and just to make everyday movements easier.</p><p>That means I slip a couple of core moves into almost every workout I do. One of those is always the <a href="https://www.tomsguide.com/wellness/fitness/not-sit-ups-or-planks-i-have-tried-almost-every-abs-exercise-going-and-this-is-the-one-i-always-include-in-my-sessions">bicycle crunch</a>, which I find a very quick and effective way to engage and strengthen my whole core.</p><p>The other move I slip into every workout has changed over time — I’ve done leg raises, <a href="https://www.tomsguide.com/wellness/workouts/forget-sit-ups-the-dying-turtle-is-my-new-favorite-core-exercise-heres-how-to-do-it">dying turtles, </a>and sit-ups — but right now my favourite is the rowing crunch.</p><p>This move mimics the motion of rowing as you bring your knees up to meet your chest, and gets the abs burning in no time at all in my experience. </p><p>It’s similar to a V-sit-up with bent knees, and sometimes also gets called the rower, boat crunch, or rowboat crunch. Whatever you call it, it's a move worth knowing about.</p><h3 class="article-body__section" id="section-how-to-do-the-rowing-crunch"><span>How to do the rowing crunch</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:3000px;"><p class="vanilla-image-block" style="padding-top:56.23%;"><img id="T4HLYJ7EjkqMSVMoWWMzo4" name="v-sit_shutterstock_2002641401.jpg" alt="a woman performing a V-Sit" src="https://cdn.mos.cms.futurecdn.net/T4HLYJ7EjkqMSVMoWWMzo4-1920-80.jpg" mos="" align="middle" fullscreen="" width="3000" height="1687" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Getty Images)</span></figcaption></figure><p>You don’t need any equipment to do the rowing crunch, though using one of the best yoga mats will make it more comfortable on hard floors.</p><ol start="1"><li>Sit on the floor and lean back to a 45-degree angle. Bend your knees and lift your feet slightly off the floor. This is your starting position.</li><li>Simultaneously lean back until your back is hovering just above the floor and extend your legs out away from you, while ‘rowing’ with your arms so your hands finish next to your chest.</li><li>Use your core muscles to pull your knees back towards your chest as you raise your torso up to meet your knees.</li></ol><p>You can make the move a little harder by pausing for a beat at the bottom of the exercise, in a hollow-bold hold position, before coming back up. I tend to do a set of 10 rowers straight after doing a set of 20 bicycle crunches as part of a circuit I do three times overall.</p><h2 class="article-body__section" id="section-benefits-of-the-rowing-crunch"><span>Benefits of the rowing crunch</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="sVJ3deaBiQVQ7EUDUrbNDE" name="abs.abs_gettyimages-1492581875" alt="woman's abs on show" src="https://cdn.mos.cms.futurecdn.net/sVJ3deaBiQVQ7EUDUrbNDE-1920-80.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>The rowing crunch blasts both the upper and lower abs as you raise your torso and lift your knees toward your chest at the same time, while your obliques help keep you balanced throughout the move.</p><p>Throughout the exercise, you have to keep your body stable, which engages the deeper core muscles and keeps them engaged the whole time, since you don’t fully release the tension in your midsection at any point during the move.</p><p>They’re challenging for people of all fitness levels, but also approachable because you don’t need any equipment. If you’re struggling to get through a full set of the move, you can do sit-ups and knee tucks to strengthen your core and build up to the rowing crunch.</p><div><blockquote><p>I find that doing the arms movements to mimic rowing, while not essential, does force me to stay in control through the exercise.</p></blockquote></div><p>I find that doing the arm movements to mimic rowing, while not essential, does force me to stay in control through the exercise and move in a smooth manner that keeps the abs engaged more effectively than jerking up and down.</p><p>There are dozens of great crunch variations that do a similar job to the rowing crunch, and if you’re getting comfortable with the move, you could try V-ups as a progression, but I’ve found them to be the ideal addition to my own workout routine alongside the bicycle crunch.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.js" async=""></script><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-to-be-more-mobile-in-their-60s-and-70s-3-low-impact-exercises-you-should-start-with" target="_blank"><strong>I teach people to be more mobile in their 60s and 70s: 3 low-impact exercises you should start with</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness/forget-burpees-the-pilates-burpee-is-beginner-friendly-and-low-impact-and-youll-love-it" target="_blank"><strong>Forget burpees —the 'Pilates burpee' is beginner-friendly and low-impact (and you’ll love it)</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/a-yoga-instructor-says-this-is-the-5-minute-yoga-routine-you-need-for-strong-and-mobile-hips-and-core-muscles" target="_blank"><strong>A yoga instructor says this is the 5-minute yoga routine you need for strong and mobile hips and core muscles</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Stay warm and dry with the 21 best fall jacketdeals — up to 55% off Patagonia, The North Face and Columbia ]]></title>
                                                                                                <dc:content><![CDATA[ <p>It's chilly enough today that I'm wearing a blanket as I type this. It's not going to get warmer for a while, so I'm searching the web for the best savings on fall jackets to keep cozy.</p><p>Top brands like Columbia, The North Face and more are dropping prices on fall apparel. You can currently get <a href="https://www.amazon.com/Mens-Fashion/b/?ie=UTF8&amp;node=7147441011&amp;ref_=outerwear&amp;enabledRefinements=%5B%7B%22rid%22%3A%22category%22%2C%22value%22%3A%22220665848011%22%2C%22ridType%22%3A%22browse%22%2C%22type%22%3A%22browse%22%7D%5D&amp;pf_rd_p=6117e3af-6ae2-437d-b1ca-67b4b5d533c9&amp;pf_rd_r=FM2HD2B6BPZW0DG4RQGD#dossier-asin-grid" target="_blank" rel="nofollow">up to 55% off jackets in Amazon's sale</a>, and I've shared the best deals below.</p><p><strong>Note: </strong>Prices may vary depending on the size and color you select. Check out any different color options available in your size to find the best deals.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><strong></strong><a href="https://www.amazon.com/Mens-Fashion/b/?ie=UTF8&amp;node=7147441011&amp;ref_=outerwear&amp;enabledRefinements=%5B%7B%22rid%22%3A%22category%22%2C%22value%22%3A%22220665848011%22%2C%22ridType%22%3A%22browse%22%2C%22type%22%3A%22browse%22%7D%5D&amp;pf_rd_p=6117e3af-6ae2-437d-b1ca-67b4b5d533c9&amp;pf_rd_r=FM2HD2B6BPZW0DG4RQGD#dossier-asin-grid" target="_blank" rel="nofollow"><strong>shop men's jacket deals at Amazon</strong></a></li><li><a href="https://www.amazon.com/Womens-Fashion/b/?ie=UTF8&amp;node=7147440011&amp;ref_=outerwear&amp;enabledRefinements=%5B%7B%22rid%22%3A%22category%22%2C%22value%22%3A%22220664405011%22%2C%22ridType%22%3A%22browse%22%2C%22type%22%3A%22browse%22%7D%5D&amp;pf_rd_p=5736cf28-0f77-4a48-b947-197646c61c80&amp;pf_rd_r=JC452A40WPQWYX1JY2B6#dossier-asin-grid" target="_blank" rel="nofollow"><strong>shop women's jacket deals at Amazon</strong></a></li><li><strong>Carhartt: </strong><a href="https://www.amazon.com/stores/page/C9532F49-E69E-4750-8B5F-A083B150E5C4" target="_blank" rel="nofollow"><strong>deals from $47</strong></a></li><li><strong>Columbia: </strong><a href="https://www.amazon.com/stores/page/DE23406A-E330-4114-BB08-B8B2CC26D99F?ingress=2&amp;lp_context_asin=B0D4C5J8H2&amp;visitId=4ce5a1ed-a607-4ddd-874d-62e254560df1&amp;store_ref=bl_ast_dp_brandlogo_sto&amp;ref_=ast_bln" target="_blank" rel="nofollow"><strong>rain jackets from $49</strong></a></li><li><strong>The North Face: </strong><a href="https://www.amazon.com/stores/page/57962A41-4E54-40A2-B7DF-E5806FDF3ED3?ingress=2&amp;lp_context_asin=B0DR64FP4S&amp;visitId=01bede14-e113-417f-9416-2d3895b97295&amp;store_ref=bl_ast_dp_brandlogo_sto&amp;ref_=ast_bln" target="_blank" rel="nofollow"><strong>fall layers from $75</strong></a></li><li><strong>Levi's: </strong><a href="https://www.amazon.com/stores/page/E2ED5571-204C-497E-B061-87022776D138" target="_blank" rel="nofollow"><strong>Trucker denim jackets from $53</strong></a></li><li><strong>Under Armour: </strong><a href="https://www.amazon.com/stores/page/74A872B9-0023-4BBE-A8FF-20259802A0F5" target="_blank" rel="nofollow"><strong>up to 40% off</strong></a></li><li><strong>Adidas: </strong><a href="https://www.amazon.com/stores/page/7F6894DD-B76B-48EB-882E-890B7A6C0E6D" target="_blank" rel="nofollow"><strong>activewear from $30</strong></a></li></ul><h3 class="article-body__section" id="section-patagonia"><span>Patagonia</span></h3><div class="product"><a data-dimension112="8440fb20-cc6e-11f1-806d-ab1dafe48af5" data-action="Deal Block" data-label="Houdini Half-Zip (Women’s)" data-dimension48="Houdini Half-Zip (Women’s)" data-dimension25="$68" href="https://www.patagonia.com/product/womens-houdini-stash-half-zip-windbreaker-pullover/23435.html?dwvar_23435_color=RWSA" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="3ysNeidsFJaun3FYH6Gh6L" name="Patagonia houdini" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3ysNeidsFJaun3FYH6Gh6L-1920-80.jpg" mos="" align="middle" fullscreen="" width="1920" height="1920" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.patagonia.com/product/womens-houdini-stash-half-zip-windbreaker-pullover/23435.html?dwvar_23435_color=RWSA" target="_blank" rel="nofollow" data-dimension112="8440fb20-cc6e-11f1-806d-ab1dafe48af5" data-action="Deal Block" data-label="Houdini Half-Zip (Women’s)" data-dimension48="Houdini Half-Zip (Women’s)" data-dimension25="$68">Houdini Half-Zip (Women’s): was $139 now $68</a></strong><br />This Houdini variant is super lightweight and packable, but skips the hood and full-length zipper in favor of a half-zip design. The highly packable half-zip is rain and wind resistant, allowing you to take it with you anytime, anywhere. <a class="view-deal button" href="https://www.patagonia.com/product/womens-houdini-stash-half-zip-windbreaker-pullover/23435.html?dwvar_23435_color=RWSA" target="_blank" rel="nofollow" data-dimension112="8440fb20-cc6e-11f1-806d-ab1dafe48af5" data-action="Deal Block" data-label="Houdini Half-Zip (Women’s)" data-dimension48="Houdini Half-Zip (Women’s)" data-dimension25="$68">View Deal</a></p></div><div class="product"><a data-dimension112="8440fbca-cc6e-11f1-8d07-6199ef018381" data-action="Deal Block" data-label="Windsweep Jacket (Men's)" data-dimension48="Windsweep Jacket (Men's)" data-dimension25="$98" href="https://www.patagonia.com/product/mens-windsweep-lightweight-windbreaker-jacket/20320.html?dwvar_20320_color=SLKH" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="UofjNVhJfqGyQgztQsCnje" name="Patagonia wind jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/UofjNVhJfqGyQgztQsCnje-1920-80.jpg" mos="" align="middle" fullscreen="" width="1920" height="1920" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.patagonia.com/product/mens-windsweep-lightweight-windbreaker-jacket/20320.html?dwvar_20320_color=SLKH" target="_blank" rel="nofollow" data-dimension112="8440fbca-cc6e-11f1-8d07-6199ef018381" data-action="Deal Block" data-label="Windsweep Jacket (Men's)" data-dimension48="Windsweep Jacket (Men's)" data-dimension25="$98">Windsweep Jacket (Men's): was $199 now $98</a></strong><br />If you're in the market for a lightweight jacket that can keep up with the elements, look no further than the Windsweep Jacket. It's made of 100% organic cotton ripstop treated with a durable water repellent (DWR). It's also packable so you can easily bring it along with you on all your adventures. <a class="view-deal button" href="https://www.patagonia.com/product/mens-windsweep-lightweight-windbreaker-jacket/20320.html?dwvar_20320_color=SLKH" target="_blank" rel="nofollow" data-dimension112="8440fbca-cc6e-11f1-8d07-6199ef018381" data-action="Deal Block" data-label="Windsweep Jacket (Men's)" data-dimension48="Windsweep Jacket (Men's)" data-dimension25="$98">View Deal</a></p></div><div class="product"><a data-dimension112="8440fc6a-cc6e-11f1-b726-23916699ee96" data-action="Deal Block" data-label="Nano Puff (Men's)" data-dimension48="Nano Puff (Men's)" data-dimension25="$113" href="https://www.patagonia.com/product/mens-nano-puff-insulated-jacket/84213.html?dwvar_84213_color=SZRD" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1608px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="6dsFHakhXVEpBKicKma5h8" name="75e2000c-2d46-444d-8459-3b0c3b90cc4c" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/6dsFHakhXVEpBKicKma5h8-1920-80.jpg" mos="" align="middle" fullscreen="" width="1608" height="1608" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.patagonia.com/product/mens-nano-puff-insulated-jacket/84213.html?dwvar_84213_color=SZRD" target="_blank" rel="nofollow" data-dimension112="8440fc6a-cc6e-11f1-b726-23916699ee96" data-action="Deal Block" data-label="Nano Puff (Men's)" data-dimension48="Nano Puff (Men's)" data-dimension25="$113">Nano Puff (Men's): was $229 now $113</a></strong><br />The Patagonia Nano Puff is a staple beloved by the Tom's Guide team. Our Senior Fitness Writer, Dan Bracaglia, wrote: "Over the past nearly two decades, my Patagonia Nano Puff has kept me warm, dry, and comfortable on no fewer than four continents while enjoying extreme activities from snowboarding the high peaks of British Columbia to horseback riding the deserts of Egypt."<a class="view-deal button" href="https://www.patagonia.com/product/mens-nano-puff-insulated-jacket/84213.html?dwvar_84213_color=SZRD" target="_blank" rel="nofollow" data-dimension112="8440fc6a-cc6e-11f1-b726-23916699ee96" data-action="Deal Block" data-label="Nano Puff (Men's)" data-dimension48="Nano Puff (Men's)" data-dimension25="$113">View Deal</a></p></div><h3 class="article-body__section" id="section-the-north-face"><span>The North Face</span></h3><div class="product"><a data-dimension112="8440fdaa-cc6e-11f1-9e8f-9bc8e10e536d" data-action="Deal Block" data-label="Women's Glacier Fleece Jacket" data-dimension48="Women's Glacier Fleece Jacket" data-dimension25="$71" href="https://www.amazon.com/NORTH-FACE-Glacier-Standard-Heather/dp/B0DR64FP4S" 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:227.98%;"><img id="kLaszbqxA5VA5RqodWXbsL" name="Women's Glacier Fleece Jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/kLaszbqxA5VA5RqodWXbsL-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1548" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/NORTH-FACE-Glacier-Standard-Heather/dp/B0DR64FP4S" target="_blank" rel="nofollow" data-dimension112="8440fdaa-cc6e-11f1-9e8f-9bc8e10e536d" data-action="Deal Block" data-label="Women's Glacier Fleece Jacket" data-dimension48="Women's Glacier Fleece Jacket" data-dimension25="$71">Women's Glacier Fleece Jacket: was $90 now $71</a></strong><br />This sleek and lightweight fleece jacket from The North Face offers plenty of stretch and breathability, making it a great choice for morning jogs, errand runs and more. With this discount, it's affordable too.<a class="view-deal button" href="https://www.amazon.com/NORTH-FACE-Glacier-Standard-Heather/dp/B0DR64FP4S" target="_blank" rel="nofollow" data-dimension112="8440fdaa-cc6e-11f1-9e8f-9bc8e10e536d" data-action="Deal Block" data-label="Women's Glacier Fleece Jacket" data-dimension48="Women's Glacier Fleece Jacket" data-dimension25="$71">View Deal</a></p></div><div class="product"><a data-dimension112="8440fe40-cc6e-11f1-b54b-b1964f093f7c" data-action="Deal Block" data-label="Antora Rain 2.0 Hooded Jacket (Women's)" data-dimension48="Antora Rain 2.0 Hooded Jacket (Women's)" data-dimension25="$110" href="https://www.amazon.com/North-Face-Waterproof-Standard-Breathable/dp/B0D4SZT3ZM" 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:191.16%;"><img id="WuNPpJEz5JkzF5Te5pT9Ub" name="Antora Rain 2.0 Hooded Jacket (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/WuNPpJEz5JkzF5Te5pT9Ub-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1298" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/North-Face-Waterproof-Standard-Breathable/dp/B0D4SZT3ZM" target="_blank" rel="nofollow" data-dimension112="8440fe40-cc6e-11f1-b54b-b1964f093f7c" data-action="Deal Block" data-label="Antora Rain 2.0 Hooded Jacket (Women's)" data-dimension48="Antora Rain 2.0 Hooded Jacket (Women's)" data-dimension25="$110">Antora Rain 2.0 Hooded Jacket (Women's): was $130 now $110</a></strong><br />Score yourself a discount on the Antora 2.0 rain jacket and protect yourself from all kinds of weather! This jacket provides plenty of mobility and room to move on all your outdoor adventures.<a class="view-deal button" href="https://www.amazon.com/North-Face-Waterproof-Standard-Breathable/dp/B0D4SZT3ZM" target="_blank" rel="nofollow" data-dimension112="8440fe40-cc6e-11f1-b54b-b1964f093f7c" data-action="Deal Block" data-label="Antora Rain 2.0 Hooded Jacket (Women's)" data-dimension48="Antora Rain 2.0 Hooded Jacket (Women's)" data-dimension25="$110">View Deal</a></p></div><div class="product"><a data-dimension112="8440feea-cc6e-11f1-8fdd-6b0e3ea2adda" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$121" href="https://www.amazon.com/dp/B0CNBL2XXG" 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:187.78%;"><img id="jLN4YbW223nKsxQxPVPWZR" name="TNF jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jLN4YbW223nKsxQxPVPWZR-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1275" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0CNBL2XXG" target="_blank" rel="nofollow" data-dimension112="8440feea-cc6e-11f1-8fdd-6b0e3ea2adda" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$121">Aconcagua 3 Jacket (Men's): was $220 now $121</a></strong><br />This lightweight puffer blends recycled down with synthetic insulation for maximum warmth and weather resistance in a tidy, easy-to-stow package. Zonal sheet insulation and a water-repellant finish round out the feature set.<a class="view-deal button" href="https://www.amazon.com/dp/B0CNBL2XXG" target="_blank" rel="nofollow" data-dimension112="8440feea-cc6e-11f1-8fdd-6b0e3ea2adda" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$121">View Deal</a></p></div><h3 class="article-body__section" id="section-arc-teryx"><span>Arc'teryx</span></h3><div class="product"><a data-dimension112="84410020-cc6e-11f1-b0c3-19f894c87fe6" data-action="Deal Block" data-label="Sima Hoody (Men's)" data-dimension48="Sima Hoody (Men's)" data-dimension25="$119" href="https://www.rei.com/product/C01372/arcteryx-sima-hoody-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1999px;"><p class="vanilla-image-block" style="padding-top:100.05%;"><img id="7ALJ3myuTiT2XsP4zXyHWg" name="Arc'teryx Sima" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/7ALJ3myuTiT2XsP4zXyHWg-1920-80.jpg" mos="" align="middle" fullscreen="" width="1999" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01372/arcteryx-sima-hoody-mens" target="_blank" rel="nofollow" data-dimension112="84410020-cc6e-11f1-b0c3-19f894c87fe6" data-action="Deal Block" data-label="Sima Hoody (Men's)" data-dimension48="Sima Hoody (Men's)" data-dimension25="$119">Sima Hoody (Men's): was $160 now $119</a></strong><br />This chic zip-up jacket is designed with backpackers and hikers in mind. Weighing just over six ounces, it's made from synthetic fabric with UPF 50+ sun protection. Nice and breathable, the fabric is also moisture-wicking to keep you dry.<a class="view-deal button" href="https://www.rei.com/product/C01372/arcteryx-sima-hoody-mens" target="_blank" rel="nofollow" data-dimension112="84410020-cc6e-11f1-b0c3-19f894c87fe6" data-action="Deal Block" data-label="Sima Hoody (Men's)" data-dimension48="Sima Hoody (Men's)" data-dimension25="$119">View Deal</a></p></div><div class="product"><a data-dimension112="844100b6-cc6e-11f1-b6b4-1bff8a6769c0" data-action="Deal Block" data-label="Squamish Hoody (Men's)" data-dimension48="Squamish Hoody (Men's)" data-dimension25="$140" href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="gU2HZNV4QV8x48bVFDMoVL" name="Arc'teryx Squamish" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gU2HZNV4QV8x48bVFDMoVL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow" data-dimension112="844100b6-cc6e-11f1-b6b4-1bff8a6769c0" data-action="Deal Block" data-label="Squamish Hoody (Men's)" data-dimension48="Squamish Hoody (Men's)" data-dimension25="$140">Squamish Hoody (Men's): was $200 now $140</a></strong><br />The Arc'teryx Squamish Hoody is completely windproof and finished with DWR, making it a versatile outer layer for those nippy wintry hikes. There's even a capped hood for keeping your face dry.<a class="view-deal button" href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow" data-dimension112="844100b6-cc6e-11f1-b6b4-1bff8a6769c0" data-action="Deal Block" data-label="Squamish Hoody (Men's)" data-dimension48="Squamish Hoody (Men's)" data-dimension25="$140">View Deal</a></p></div><h3 class="article-body__section" id="section-adidas"><span>Adidas</span></h3><div class="product"><a data-dimension112="844101ec-cc6e-11f1-96a8-c3338539050f" data-action="Deal Block" data-label="Terrex Multi-Synthetic Insulated Hiking Jacket (Men's)" data-dimension48="Terrex Multi-Synthetic Insulated Hiking Jacket (Men's)" data-dimension25="$28" href="https://www.amazon.com/adidas-Standard-Multi-Synthetic-Insulated-Cardboard/dp/B0DJWNR8W6" 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:200.29%;"><img id="SkBUz9AdxzZ3oojsDsSiK8" name="Terrex Multi-Synthetic Insulated Hiking Jacket (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/SkBUz9AdxzZ3oojsDsSiK8-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1360" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/adidas-Standard-Multi-Synthetic-Insulated-Cardboard/dp/B0DJWNR8W6" target="_blank" rel="nofollow" data-dimension112="844101ec-cc6e-11f1-96a8-c3338539050f" data-action="Deal Block" data-label="Terrex Multi-Synthetic Insulated Hiking Jacket (Men's)" data-dimension48="Terrex Multi-Synthetic Insulated Hiking Jacket (Men's)" data-dimension25="$28">Terrex Multi-Synthetic Insulated Hiking Jacket (Men's): was $140 now $28</a></strong><br />I couldn't believe this 80% discount when I first saw it! This is a huge steal for an insulated hiking jacket. It's water-repellent to protect you from light rain and will keep you warm both on the trails and on casual walks.<a class="view-deal button" href="https://www.amazon.com/adidas-Standard-Multi-Synthetic-Insulated-Cardboard/dp/B0DJWNR8W6" target="_blank" rel="nofollow" data-dimension112="844101ec-cc6e-11f1-96a8-c3338539050f" data-action="Deal Block" data-label="Terrex Multi-Synthetic Insulated Hiking Jacket (Men's)" data-dimension48="Terrex Multi-Synthetic Insulated Hiking Jacket (Men's)" data-dimension25="$28">View Deal</a></p></div><div class="product"><a data-dimension112="8441028c-cc6e-11f1-a780-bb570b16e96e" data-action="Deal Block" data-label="All Szn Fleece Full-Zip Hoodie (Men's)" data-dimension48="All Szn Fleece Full-Zip Hoodie (Men's)" data-dimension25="$43" href="https://www.amazon.com/adidas-Fleece-Hoodie-Earth-Strata/dp/B0CMRRN52Q" 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:203.24%;"><img id="4Pr2wXN4KT6RTb89w7fzJb" name="7177i++ESRL._AC_SX679_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4Pr2wXN4KT6RTb89w7fzJb-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1380" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/adidas-Fleece-Hoodie-Earth-Strata/dp/B0CMRRN52Q" target="_blank" rel="nofollow" data-dimension112="8441028c-cc6e-11f1-a780-bb570b16e96e" data-action="Deal Block" data-label="All Szn Fleece Full-Zip Hoodie (Men's)" data-dimension48="All Szn Fleece Full-Zip Hoodie (Men's)" data-dimension25="$43">All Szn Fleece Full-Zip Hoodie (Men's): was $65 now $43</a></strong><br />This is one of my favorite items from Adidas' lineup. I'm a big fan of this hoodie's subtle Earth Strata colorway, and the loose fit means it's great for workouts or casual wear. Plus, like the name suggests, you can wear it all year round.<a class="view-deal button" href="https://www.amazon.com/adidas-Fleece-Hoodie-Earth-Strata/dp/B0CMRRN52Q" target="_blank" rel="nofollow" data-dimension112="8441028c-cc6e-11f1-a780-bb570b16e96e" data-action="Deal Block" data-label="All Szn Fleece Full-Zip Hoodie (Men's)" data-dimension48="All Szn Fleece Full-Zip Hoodie (Men's)" data-dimension25="$43">View Deal</a></p></div><h3 class="article-body__section" id="section-carhartt"><span>Carhartt</span></h3><div class="product"><a data-dimension112="221ce0e6-cc6c-11f1-841f-712b3b8b6ad4" data-action="Deal Block" data-label="Rain Defender Packable Anorak (Women's)" data-dimension48="Rain Defender Packable Anorak (Women's)" data-dimension25="$47" href="https://www.amazon.com/Carhartt-Defender-Lightweight-Packable-Asphalt/dp/B0BNJN3LDM" 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:221.80%;"><img id="W7hPuJg734Jg83fm9As5Qb" name="Carhartt rain jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/W7hPuJg734Jg83fm9As5Qb-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1506" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Carhartt-Defender-Lightweight-Packable-Asphalt/dp/B0BNJN3LDM" target="_blank" rel="nofollow" data-dimension112="221ce0e6-cc6c-11f1-841f-712b3b8b6ad4" data-action="Deal Block" data-label="Rain Defender Packable Anorak (Women's)" data-dimension48="Rain Defender Packable Anorak (Women's)" data-dimension25="$47">Rain Defender Packable Anorak (Women's): was $79 now $47</a></strong><br />The Rain Defender Anorak is a lightweight and packable water and wind-resistant half-zip with a large kangaroo-style velcro pocket up front and hidden zippered hand pockets along the side. The two-tone design gives off retro vibes while the roomy, loose-fit cut shouldn't restrict movement. <a class="view-deal button" href="https://www.amazon.com/Carhartt-Defender-Lightweight-Packable-Asphalt/dp/B0BNJN3LDM" target="_blank" rel="nofollow" data-dimension112="221ce0e6-cc6c-11f1-841f-712b3b8b6ad4" data-action="Deal Block" data-label="Rain Defender Packable Anorak (Women's)" data-dimension48="Rain Defender Packable Anorak (Women's)" data-dimension25="$47">View Deal</a></p></div><div class="product"><a data-dimension112="221ce140-cc6c-11f1-b9c1-ff5bd59d9332" data-action="Deal Block" data-label="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension48="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension25="$58" href="https://www.amazon.com/Carhartt-Relaxed-Full-Zip-Long-Sleeve-T-Shirt/dp/B0D3J857CC" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:594px;"><p class="vanilla-image-block" style="padding-top:168.18%;"><img id="XVAtjBrciTnPeT2AD3fLvm" name="Long Sleeve Full zip" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XVAtjBrciTnPeT2AD3fLvm-1920-80.jpg" mos="" align="middle" fullscreen="" width="594" height="999" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Carhartt-Relaxed-Full-Zip-Long-Sleeve-T-Shirt/dp/B0D3J857CC" target="_blank" rel="nofollow" data-dimension112="221ce140-cc6c-11f1-b9c1-ff5bd59d9332" data-action="Deal Block" data-label="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension48="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension25="$58">Force Relaxed Fit Full-Zip Long-Sleeve (Men's): was $84 now $58</a></strong><br />Perfect for a casual stroll, low-intensity workout or a longer run, this versatile layer features Carhartt Force technology to wick sweat, dry fast, and fight odors. It's a full zip and allows for a full range of motion too. <a class="view-deal button" href="https://www.amazon.com/Carhartt-Relaxed-Full-Zip-Long-Sleeve-T-Shirt/dp/B0D3J857CC" target="_blank" rel="nofollow" data-dimension112="221ce140-cc6c-11f1-b9c1-ff5bd59d9332" data-action="Deal Block" data-label="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension48="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension25="$58">View Deal</a></p></div><div class="product"><a data-dimension112="221ce1a4-cc6c-11f1-87f5-4f1e36b02c49" data-action="Deal Block" data-label="Monterey Jacket (Women's)" data-dimension48="Monterey Jacket (Women's)" data-dimension25="$64" href="https://www.amazon.com/Carhartt-Womens-Defender-Lightweight-Packable/dp/B0F96WVJNC?" 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:201.18%;"><img id="WrHCmC5ZrvbsGGNpQnXLYL" name="Monterrey Jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/WrHCmC5ZrvbsGGNpQnXLYL-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1366" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Carhartt-Womens-Defender-Lightweight-Packable/dp/B0F96WVJNC?" target="_blank" rel="nofollow" data-dimension112="221ce1a4-cc6c-11f1-87f5-4f1e36b02c49" data-action="Deal Block" data-label="Monterey Jacket (Women's)" data-dimension48="Monterey Jacket (Women's)" data-dimension25="$64">Monterey Jacket (Women's): was $99 now $64</a></strong><br />Don't get caught in a rainstorm without this jacket. It features waterproof, breathable technology that stops water from getting in but lets sweat get out. It also has Wind Fighter technology to combat the elements. <a class="view-deal button" href="https://www.amazon.com/Carhartt-Womens-Defender-Lightweight-Packable/dp/B0F96WVJNC?" target="_blank" rel="nofollow" data-dimension112="221ce1a4-cc6c-11f1-87f5-4f1e36b02c49" data-action="Deal Block" data-label="Monterey Jacket (Women's)" data-dimension48="Monterey Jacket (Women's)" data-dimension25="$64">View Deal</a></p></div><div class="product"><a data-dimension112="221ce1fe-cc6c-11f1-919a-3beba15dc1c5" data-action="Deal Block" data-label="Rain Defender Jacket (Men's)" data-dimension48="Rain Defender Jacket (Men's)" data-dimension25="$74" href="https://www.amazon.com/Carhartt-Defender-Relaxed-Jacket-Ocean/dp/B0F8PP4JZ2" 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:127.84%;"><img id="VVpm8JrkWovdG4VCm3q4We" name="Rain Defender Jacket (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/VVpm8JrkWovdG4VCm3q4We-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="868" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Carhartt-Defender-Relaxed-Jacket-Ocean/dp/B0F8PP4JZ2" target="_blank" rel="nofollow" data-dimension112="221ce1fe-cc6c-11f1-919a-3beba15dc1c5" data-action="Deal Block" data-label="Rain Defender Jacket (Men's)" data-dimension48="Rain Defender Jacket (Men's)" data-dimension25="$74">Rain Defender Jacket (Men's): was $99 now $74</a></strong><br />The Carhartt Rain Defender Jacket is now on sale from $74. It's perfect to take on wind and rain, while keeping you warm and dry. It's durable and moves with you thanks to its Rugged Flex stretch technology.<a class="view-deal button" href="https://www.amazon.com/Carhartt-Defender-Relaxed-Jacket-Ocean/dp/B0F8PP4JZ2" target="_blank" rel="nofollow" data-dimension112="221ce1fe-cc6c-11f1-919a-3beba15dc1c5" data-action="Deal Block" data-label="Rain Defender Jacket (Men's)" data-dimension48="Rain Defender Jacket (Men's)" data-dimension25="$74">View Deal</a></p></div><h3 class="article-body__section" id="section-columbia"><span>Columbia</span></h3><div class="product"><a data-dimension112="221ce370-cc6c-11f1-96fb-d1bf87bef039" data-action="Deal Block" data-label="Switchback Jacket (Women's)" data-dimension48="Switchback Jacket (Women's)" data-dimension25="$37" href="https://www.amazon.com/dp/B0CLR14KFG?" 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:164.95%;"><img id="wS5fq4uyAmDFumApbN8rJR" name="Columbia Switchback" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/wS5fq4uyAmDFumApbN8rJR-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1120" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0CLR14KFG?" target="_blank" rel="nofollow" data-dimension112="221ce370-cc6c-11f1-96fb-d1bf87bef039" data-action="Deal Block" data-label="Switchback Jacket (Women's)" data-dimension48="Switchback Jacket (Women's)" data-dimension25="$37">Switchback Jacket (Women's): was $70 now $37</a></strong><br />This lightweight packable jacket takes up minimal real estate, so there's no excuse not to bring it along on your next outdoor outing. Plus, a hidden hood deploys from the collar when needed and a drawstring hem and adjustable cuffs ensure a watertight fit. <a class="view-deal button" href="https://www.amazon.com/dp/B0CLR14KFG?" target="_blank" rel="nofollow" data-dimension112="221ce370-cc6c-11f1-96fb-d1bf87bef039" data-action="Deal Block" data-label="Switchback Jacket (Women's)" data-dimension48="Switchback Jacket (Women's)" data-dimension25="$37">View Deal</a></p></div><div class="product"><a data-dimension112="221ce3ca-cc6c-11f1-98bd-71490c3642a7" data-action="Deal Block" data-label="Panorama Full Zip (Women's)" data-dimension48="Panorama Full Zip (Women's)" data-dimension25="$45" href="https://www.amazon.com/Columbia-Womens-Panorama-Moonvista-Large/dp/B0CLR9N5PW" 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:202.65%;"><img id="BmSeKyYnTe5vd4ghNKRCf8" name="columbia fleece" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/BmSeKyYnTe5vd4ghNKRCf8-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1376" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Columbia-Womens-Panorama-Moonvista-Large/dp/B0CLR9N5PW" target="_blank" rel="nofollow" data-dimension112="221ce3ca-cc6c-11f1-98bd-71490c3642a7" data-action="Deal Block" data-label="Panorama Full Zip (Women's)" data-dimension48="Panorama Full Zip (Women's)" data-dimension25="$45">Panorama Full Zip (Women's): was $100 now $45</a></strong><br />From a light hike to cozying up by the fire, this top-rated Sherpa fleece full zip that's lined with a soft, suede-like material, is perfect for all your outdoor adventures when the air is a bit crisp. It's cut with that classic style and fit you can count on.<a class="view-deal button" href="https://www.amazon.com/Columbia-Womens-Panorama-Moonvista-Large/dp/B0CLR9N5PW" target="_blank" rel="nofollow" data-dimension112="221ce3ca-cc6c-11f1-98bd-71490c3642a7" data-action="Deal Block" data-label="Panorama Full Zip (Women's)" data-dimension48="Panorama Full Zip (Women's)" data-dimension25="$45">View Deal</a></p></div><div class="product"><a data-dimension112="221ce424-cc6c-11f1-bd23-f3875692386f" data-action="Deal Block" data-label="Ascender Softshell Rain Jacket (Men's)" data-dimension48="Ascender Softshell Rain Jacket (Men's)" data-dimension25="$52" href="https://www.amazon.com/Columbia-Ascender-Softshell-Jacket-Black/dp/B0CLRBK7P2" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:829px;"><p class="vanilla-image-block" style="padding-top:100.12%;"><img id="RxbCzBdr6qyZyeYxwMo4jE" name="Columbia-m-ascender" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/RxbCzBdr6qyZyeYxwMo4jE-1920-80.jpg" mos="" align="middle" fullscreen="" width="829" height="830" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Columbia-Ascender-Softshell-Jacket-Black/dp/B0CLRBK7P2" target="_blank" rel="nofollow" data-dimension112="221ce424-cc6c-11f1-bd23-f3875692386f" data-action="Deal Block" data-label="Ascender Softshell Rain Jacket (Men's)" data-dimension48="Ascender Softshell Rain Jacket (Men's)" data-dimension25="$52">Ascender Softshell Rain Jacket (Men's): was $125 now $52</a></strong><br />This stretchy, chic softshell isn't for torrential downpours but will keep you dry in light rain and drizzle. Made from 100% polyester, it features zippered hand and chest pockets, an abrasion-resistant chin guard and an adjustable hem and cuffs. <a class="view-deal button" href="https://www.amazon.com/Columbia-Ascender-Softshell-Jacket-Black/dp/B0CLRBK7P2" target="_blank" rel="nofollow" data-dimension112="221ce424-cc6c-11f1-bd23-f3875692386f" data-action="Deal Block" data-label="Ascender Softshell Rain Jacket (Men's)" data-dimension48="Ascender Softshell Rain Jacket (Men's)" data-dimension25="$52">View Deal</a></p></div><div class="product"><a data-dimension112="221ce47e-cc6c-11f1-a39a-05e6a8c98b18" data-action="Deal Block" data-label="Women’s Kruser Ridge III Softshell Jacket" data-dimension48="Women’s Kruser Ridge III Softshell Jacket" data-dimension25="$87" href="https://www.amazon.com/Columbia-Womens-Kruser-Softshell-Jacket/dp/B0CLR7V452" 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:184.39%;"><img id="6Djt9vujjJqFV5FhisPWRc" name="61p6G9ZDclL._AC_SX679_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/6Djt9vujjJqFV5FhisPWRc-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1252" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Columbia-Womens-Kruser-Softshell-Jacket/dp/B0CLR7V452" target="_blank" rel="nofollow" data-dimension112="221ce47e-cc6c-11f1-a39a-05e6a8c98b18" data-action="Deal Block" data-label="Women’s Kruser Ridge III Softshell Jacket" data-dimension48="Women’s Kruser Ridge III Softshell Jacket" data-dimension25="$87">Women’s Kruser Ridge III Softshell Jacket: was $110 now $87</a></strong><br />A softshell jacket for $87? This is an amazing price for a water<em> and</em> rain-resistant shell that’ll keep you dry without getting overly sweaty as the weather changes. With large zipped pockets for your essentials and a drawcord hem to keep the cold out, this is a fantastic deal on a great jacket. <a class="view-deal button" href="https://www.amazon.com/Columbia-Womens-Kruser-Softshell-Jacket/dp/B0CLR7V452" target="_blank" rel="nofollow" data-dimension112="221ce47e-cc6c-11f1-a39a-05e6a8c98b18" data-action="Deal Block" data-label="Women’s Kruser Ridge III Softshell Jacket" data-dimension48="Women’s Kruser Ridge III Softshell Jacket" data-dimension25="$87">View Deal</a></p></div><div class="product"><a data-dimension112="221ce4e2-cc6c-11f1-862e-a5fbae305984" data-action="Deal Block" data-label="Powder Lite II Jacket (Men's)" data-dimension48="Powder Lite II Jacket (Men's)" data-dimension25="$115" href="https://www.amazon.com/Columbia-Powder-Jacket-Black-Large/dp/B0CLRBRZHS" 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:189.84%;"><img id="BtaCy7tDVwYLGzNAQeJusG" name="Powder Lite II Jacket (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/BtaCy7tDVwYLGzNAQeJusG-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1289" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Columbia-Powder-Jacket-Black-Large/dp/B0CLRBRZHS" target="_blank" rel="nofollow" data-dimension112="221ce4e2-cc6c-11f1-862e-a5fbae305984" data-action="Deal Block" data-label="Powder Lite II Jacket (Men's)" data-dimension48="Powder Lite II Jacket (Men's)" data-dimension25="$115">Powder Lite II Jacket (Men's): was $165 now $115</a></strong><br />Columbia’s Omni-Heat thermal-reflective lining retains your body's own warmth, and the puffer also has a water-resistant outer layer for wet weather. Plus, it stows easily and is super lightweight if you enjoy hiking.<a class="view-deal button" href="https://www.amazon.com/Columbia-Powder-Jacket-Black-Large/dp/B0CLRBRZHS" target="_blank" rel="nofollow" data-dimension112="221ce4e2-cc6c-11f1-862e-a5fbae305984" data-action="Deal Block" data-label="Powder Lite II Jacket (Men's)" data-dimension48="Powder Lite II Jacket (Men's)" data-dimension25="$115">View Deal</a></p></div><h3 class="article-body__section" id="section-under-armour"><span>Under Armour</span></h3><div class="product"><a data-dimension112="221ce870-cc6c-11f1-aae4-213d2af84719" data-action="Deal Block" data-label="Motion Jacket (Women's)" data-dimension48="Motion Jacket (Women's)" data-dimension25="$36" href="https://www.amazon.com/Under-Armour-Womens-Motion-Jacket/dp/B08LN1MLQS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:433px;"><p class="vanilla-image-block" style="padding-top:230.95%;"><img id="CmtEvXMpkpp7SbDcxDYzY9" name="Motion Jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/CmtEvXMpkpp7SbDcxDYzY9-1920-80.jpg" mos="" align="middle" fullscreen="" width="433" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Under-Armour-Womens-Motion-Jacket/dp/B08LN1MLQS" target="_blank" rel="nofollow" data-dimension112="221ce870-cc6c-11f1-aae4-213d2af84719" data-action="Deal Block" data-label="Motion Jacket (Women's)" data-dimension48="Motion Jacket (Women's)" data-dimension25="$36">Motion Jacket (Women's): was $55 now $36</a></strong><br />This stylish jacket is made of ultra soft fabric that is both breathable and comfortable. Similar to the flare pants above, it features four-way stretch material that helps you move in any direction.<a class="view-deal button" href="https://www.amazon.com/Under-Armour-Womens-Motion-Jacket/dp/B08LN1MLQS" target="_blank" rel="nofollow" data-dimension112="221ce870-cc6c-11f1-aae4-213d2af84719" data-action="Deal Block" data-label="Motion Jacket (Women's)" data-dimension48="Motion Jacket (Women's)" data-dimension25="$36">View Deal</a></p></div><div class="product"><a data-dimension112="221ce924-cc6c-11f1-8f1d-21687bef681b" data-action="Deal Block" data-label="Rival Woven Windbreaker (Men's)" data-dimension48="Rival Woven Windbreaker (Men's)" data-dimension25="$50" href="https://www.amazon.com/Under-Armour-Rival-Windbreaker-Medium/dp/B0D1669X2T" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:442px;"><p class="vanilla-image-block" style="padding-top:167.65%;"><img id="6L4HJj86LoQsb7ZXGJJ2eR" name="Rival Woven Windbreaker (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/6L4HJj86LoQsb7ZXGJJ2eR-1920-80.jpg" mos="" align="middle" fullscreen="" width="442" height="741" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Under-Armour-Rival-Windbreaker-Medium/dp/B0D1669X2T" target="_blank" rel="nofollow" data-dimension112="221ce924-cc6c-11f1-8f1d-21687bef681b" data-action="Deal Block" data-label="Rival Woven Windbreaker (Men's)" data-dimension48="Rival Woven Windbreaker (Men's)" data-dimension25="$50">Rival Woven Windbreaker (Men's): was $65 now $50</a></strong><br />This Under Armour windbreaker will make wind the least of your worries. It's breathable, while keeping out light wind and rain, and has a lightweight feel.<a class="view-deal button" href="https://www.amazon.com/Under-Armour-Rival-Windbreaker-Medium/dp/B0D1669X2T" target="_blank" rel="nofollow" data-dimension112="221ce924-cc6c-11f1-8f1d-21687bef681b" data-action="Deal Block" data-label="Rival Woven Windbreaker (Men's)" data-dimension48="Rival Woven Windbreaker (Men's)" data-dimension25="$50">View Deal</a></p></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness/stay-warm-and-dry-with-the-21-best-fall-jacket-deals-up-to-55-percent-off-patagonia-the-north-face-and-columbia</link>
                                                                            <description>
                            <![CDATA[ These are the best jacket deals you can get right now — I'm sharing the best deals on everything you need to keep warm. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">aVZbQGehM8VokH4RGEs968</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/JTCccVyD87tsqRJbDHopxB-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 20 Oct 2026 10:36:13 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Fitness]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                <author><![CDATA[ millie.daviswilliams@futurenet.com (Millie Davis-Williams) ]]></author>                    <dc:creator><![CDATA[ Millie Davis-Williams ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/WU6pa7hKuxs5ScCoqcXYWA-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Millie is a Deals Editor at Tom&#039;s Guide specializing in tech deals content. Based in London, Millie has spent a lifetime stubbornly refusing to pay full price on any possible purchase. She has years of searching for the best discounts on the latest and greatest phones, TVs and gadgets under her belt, and knows how to sort the best deals from the rest. Helping readers save on the products they want is her mission, whether it’s an Apple Watch or a new tablet.&lt;/p&gt;&lt;p&gt;Since working at Tom’s Guide, Millie has covered retail events like Prime Day, Black Friday and Cyber Monday extensively, meaning she knows the products readers are looking for and the best times of year to hit “purchase.”&lt;/p&gt;&lt;p&gt;When she’s not looking for discounts, Millie covers news and writes how-to articles about everything from phones, streaming devices, and headphones to apps and video games.&lt;/p&gt;&lt;p&gt;In her spare time, Millie enjoys reading, gaming on her Nintendo Switch and creating digital art. She’s also a fan of watching Disney movies and collecting plush (the latter having totally taken over her bedroom.)&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/JTCccVyD87tsqRJbDHopxB-1920-80.jpg">
                                                            <media:credit><![CDATA[Patagonia (Future credit &amp;quot;TG Savings Squad&amp;quot; badge)]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[the patagonia houdini jacket being worn by a male hiker outside]]></media:description>                                                            <media:text><![CDATA[the patagonia houdini jacket being worn by a male hiker outside]]></media:text>
                                <media:title type="plain"><![CDATA[the patagonia houdini jacket being worn by a male hiker outside]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/JTCccVyD87tsqRJbDHopxB-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>It's chilly enough today that I'm wearing a blanket as I type this. It's not going to get warmer for a while, so I'm searching the web for the best savings on fall jackets to keep cozy.</p><p>Top brands like Columbia, The North Face and more are dropping prices on fall apparel. You can currently get <a href="https://www.amazon.com/Mens-Fashion/b/?ie=UTF8&amp;node=7147441011&amp;ref_=outerwear&amp;enabledRefinements=%5B%7B%22rid%22%3A%22category%22%2C%22value%22%3A%22220665848011%22%2C%22ridType%22%3A%22browse%22%2C%22type%22%3A%22browse%22%7D%5D&amp;pf_rd_p=6117e3af-6ae2-437d-b1ca-67b4b5d533c9&amp;pf_rd_r=FM2HD2B6BPZW0DG4RQGD#dossier-asin-grid" target="_blank" rel="nofollow">up to 55% off jackets in Amazon's sale</a>, and I've shared the best deals below.</p><p><strong>Note: </strong>Prices may vary depending on the size and color you select. Check out any different color options available in your size to find the best deals.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><strong></strong><a href="https://www.amazon.com/Mens-Fashion/b/?ie=UTF8&amp;node=7147441011&amp;ref_=outerwear&amp;enabledRefinements=%5B%7B%22rid%22%3A%22category%22%2C%22value%22%3A%22220665848011%22%2C%22ridType%22%3A%22browse%22%2C%22type%22%3A%22browse%22%7D%5D&amp;pf_rd_p=6117e3af-6ae2-437d-b1ca-67b4b5d533c9&amp;pf_rd_r=FM2HD2B6BPZW0DG4RQGD#dossier-asin-grid" target="_blank" rel="nofollow"><strong>shop men's jacket deals at Amazon</strong></a></li><li><a href="https://www.amazon.com/Womens-Fashion/b/?ie=UTF8&amp;node=7147440011&amp;ref_=outerwear&amp;enabledRefinements=%5B%7B%22rid%22%3A%22category%22%2C%22value%22%3A%22220664405011%22%2C%22ridType%22%3A%22browse%22%2C%22type%22%3A%22browse%22%7D%5D&amp;pf_rd_p=5736cf28-0f77-4a48-b947-197646c61c80&amp;pf_rd_r=JC452A40WPQWYX1JY2B6#dossier-asin-grid" target="_blank" rel="nofollow"><strong>shop women's jacket deals at Amazon</strong></a></li><li><strong>Carhartt: </strong><a href="https://www.amazon.com/stores/page/C9532F49-E69E-4750-8B5F-A083B150E5C4" target="_blank" rel="nofollow"><strong>deals from $47</strong></a></li><li><strong>Columbia: </strong><a href="https://www.amazon.com/stores/page/DE23406A-E330-4114-BB08-B8B2CC26D99F?ingress=2&amp;lp_context_asin=B0D4C5J8H2&amp;visitId=4ce5a1ed-a607-4ddd-874d-62e254560df1&amp;store_ref=bl_ast_dp_brandlogo_sto&amp;ref_=ast_bln" target="_blank" rel="nofollow"><strong>rain jackets from $49</strong></a></li><li><strong>The North Face: </strong><a href="https://www.amazon.com/stores/page/57962A41-4E54-40A2-B7DF-E5806FDF3ED3?ingress=2&amp;lp_context_asin=B0DR64FP4S&amp;visitId=01bede14-e113-417f-9416-2d3895b97295&amp;store_ref=bl_ast_dp_brandlogo_sto&amp;ref_=ast_bln" target="_blank" rel="nofollow"><strong>fall layers from $75</strong></a></li><li><strong>Levi's: </strong><a href="https://www.amazon.com/stores/page/E2ED5571-204C-497E-B061-87022776D138" target="_blank" rel="nofollow"><strong>Trucker denim jackets from $53</strong></a></li><li><strong>Under Armour: </strong><a href="https://www.amazon.com/stores/page/74A872B9-0023-4BBE-A8FF-20259802A0F5" target="_blank" rel="nofollow"><strong>up to 40% off</strong></a></li><li><strong>Adidas: </strong><a href="https://www.amazon.com/stores/page/7F6894DD-B76B-48EB-882E-890B7A6C0E6D" target="_blank" rel="nofollow"><strong>activewear from $30</strong></a></li></ul><h3 class="article-body__section" id="section-patagonia"><span>Patagonia</span></h3><div class="product"><a data-dimension112="8440fb20-cc6e-11f1-806d-ab1dafe48af5" data-action="Deal Block" data-label="Houdini Half-Zip (Women’s)" data-dimension48="Houdini Half-Zip (Women’s)" data-dimension25="$68" href="https://www.patagonia.com/product/womens-houdini-stash-half-zip-windbreaker-pullover/23435.html?dwvar_23435_color=RWSA" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="3ysNeidsFJaun3FYH6Gh6L" name="Patagonia houdini" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3ysNeidsFJaun3FYH6Gh6L-1920-80.jpg" mos="" align="middle" fullscreen="" width="1920" height="1920" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.patagonia.com/product/womens-houdini-stash-half-zip-windbreaker-pullover/23435.html?dwvar_23435_color=RWSA" target="_blank" rel="nofollow" data-dimension112="8440fb20-cc6e-11f1-806d-ab1dafe48af5" data-action="Deal Block" data-label="Houdini Half-Zip (Women’s)" data-dimension48="Houdini Half-Zip (Women’s)" data-dimension25="$68">Houdini Half-Zip (Women’s): was $139 now $68</a></strong><br />This Houdini variant is super lightweight and packable, but skips the hood and full-length zipper in favor of a half-zip design. The highly packable half-zip is rain and wind resistant, allowing you to take it with you anytime, anywhere. <a class="view-deal button" href="https://www.patagonia.com/product/womens-houdini-stash-half-zip-windbreaker-pullover/23435.html?dwvar_23435_color=RWSA" target="_blank" rel="nofollow" data-dimension112="8440fb20-cc6e-11f1-806d-ab1dafe48af5" data-action="Deal Block" data-label="Houdini Half-Zip (Women’s)" data-dimension48="Houdini Half-Zip (Women’s)" data-dimension25="$68">View Deal</a></p></div><div class="product"><a data-dimension112="8440fbca-cc6e-11f1-8d07-6199ef018381" data-action="Deal Block" data-label="Windsweep Jacket (Men's)" data-dimension48="Windsweep Jacket (Men's)" data-dimension25="$98" href="https://www.patagonia.com/product/mens-windsweep-lightweight-windbreaker-jacket/20320.html?dwvar_20320_color=SLKH" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="UofjNVhJfqGyQgztQsCnje" name="Patagonia wind jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/UofjNVhJfqGyQgztQsCnje-1920-80.jpg" mos="" align="middle" fullscreen="" width="1920" height="1920" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.patagonia.com/product/mens-windsweep-lightweight-windbreaker-jacket/20320.html?dwvar_20320_color=SLKH" target="_blank" rel="nofollow" data-dimension112="8440fbca-cc6e-11f1-8d07-6199ef018381" data-action="Deal Block" data-label="Windsweep Jacket (Men's)" data-dimension48="Windsweep Jacket (Men's)" data-dimension25="$98">Windsweep Jacket (Men's): was $199 now $98</a></strong><br />If you're in the market for a lightweight jacket that can keep up with the elements, look no further than the Windsweep Jacket. It's made of 100% organic cotton ripstop treated with a durable water repellent (DWR). It's also packable so you can easily bring it along with you on all your adventures. <a class="view-deal button" href="https://www.patagonia.com/product/mens-windsweep-lightweight-windbreaker-jacket/20320.html?dwvar_20320_color=SLKH" target="_blank" rel="nofollow" data-dimension112="8440fbca-cc6e-11f1-8d07-6199ef018381" data-action="Deal Block" data-label="Windsweep Jacket (Men's)" data-dimension48="Windsweep Jacket (Men's)" data-dimension25="$98">View Deal</a></p></div><div class="product"><a data-dimension112="8440fc6a-cc6e-11f1-b726-23916699ee96" data-action="Deal Block" data-label="Nano Puff (Men's)" data-dimension48="Nano Puff (Men's)" data-dimension25="$113" href="https://www.patagonia.com/product/mens-nano-puff-insulated-jacket/84213.html?dwvar_84213_color=SZRD" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1608px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="6dsFHakhXVEpBKicKma5h8" name="75e2000c-2d46-444d-8459-3b0c3b90cc4c" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/6dsFHakhXVEpBKicKma5h8-1920-80.jpg" mos="" align="middle" fullscreen="" width="1608" height="1608" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.patagonia.com/product/mens-nano-puff-insulated-jacket/84213.html?dwvar_84213_color=SZRD" target="_blank" rel="nofollow" data-dimension112="8440fc6a-cc6e-11f1-b726-23916699ee96" data-action="Deal Block" data-label="Nano Puff (Men's)" data-dimension48="Nano Puff (Men's)" data-dimension25="$113">Nano Puff (Men's): was $229 now $113</a></strong><br />The Patagonia Nano Puff is a staple beloved by the Tom's Guide team. Our Senior Fitness Writer, Dan Bracaglia, wrote: "Over the past nearly two decades, my Patagonia Nano Puff has kept me warm, dry, and comfortable on no fewer than four continents while enjoying extreme activities from snowboarding the high peaks of British Columbia to horseback riding the deserts of Egypt."<a class="view-deal button" href="https://www.patagonia.com/product/mens-nano-puff-insulated-jacket/84213.html?dwvar_84213_color=SZRD" target="_blank" rel="nofollow" data-dimension112="8440fc6a-cc6e-11f1-b726-23916699ee96" data-action="Deal Block" data-label="Nano Puff (Men's)" data-dimension48="Nano Puff (Men's)" data-dimension25="$113">View Deal</a></p></div><h3 class="article-body__section" id="section-the-north-face"><span>The North Face</span></h3><div class="product"><a data-dimension112="8440fdaa-cc6e-11f1-9e8f-9bc8e10e536d" data-action="Deal Block" data-label="Women's Glacier Fleece Jacket" data-dimension48="Women's Glacier Fleece Jacket" data-dimension25="$71" href="https://www.amazon.com/NORTH-FACE-Glacier-Standard-Heather/dp/B0DR64FP4S" 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:227.98%;"><img id="kLaszbqxA5VA5RqodWXbsL" name="Women's Glacier Fleece Jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/kLaszbqxA5VA5RqodWXbsL-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1548" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/NORTH-FACE-Glacier-Standard-Heather/dp/B0DR64FP4S" target="_blank" rel="nofollow" data-dimension112="8440fdaa-cc6e-11f1-9e8f-9bc8e10e536d" data-action="Deal Block" data-label="Women's Glacier Fleece Jacket" data-dimension48="Women's Glacier Fleece Jacket" data-dimension25="$71">Women's Glacier Fleece Jacket: was $90 now $71</a></strong><br />This sleek and lightweight fleece jacket from The North Face offers plenty of stretch and breathability, making it a great choice for morning jogs, errand runs and more. With this discount, it's affordable too.<a class="view-deal button" href="https://www.amazon.com/NORTH-FACE-Glacier-Standard-Heather/dp/B0DR64FP4S" target="_blank" rel="nofollow" data-dimension112="8440fdaa-cc6e-11f1-9e8f-9bc8e10e536d" data-action="Deal Block" data-label="Women's Glacier Fleece Jacket" data-dimension48="Women's Glacier Fleece Jacket" data-dimension25="$71">View Deal</a></p></div><div class="product"><a data-dimension112="8440fe40-cc6e-11f1-b54b-b1964f093f7c" data-action="Deal Block" data-label="Antora Rain 2.0 Hooded Jacket (Women's)" data-dimension48="Antora Rain 2.0 Hooded Jacket (Women's)" data-dimension25="$110" href="https://www.amazon.com/North-Face-Waterproof-Standard-Breathable/dp/B0D4SZT3ZM" 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:191.16%;"><img id="WuNPpJEz5JkzF5Te5pT9Ub" name="Antora Rain 2.0 Hooded Jacket (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/WuNPpJEz5JkzF5Te5pT9Ub-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1298" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/North-Face-Waterproof-Standard-Breathable/dp/B0D4SZT3ZM" target="_blank" rel="nofollow" data-dimension112="8440fe40-cc6e-11f1-b54b-b1964f093f7c" data-action="Deal Block" data-label="Antora Rain 2.0 Hooded Jacket (Women's)" data-dimension48="Antora Rain 2.0 Hooded Jacket (Women's)" data-dimension25="$110">Antora Rain 2.0 Hooded Jacket (Women's): was $130 now $110</a></strong><br />Score yourself a discount on the Antora 2.0 rain jacket and protect yourself from all kinds of weather! This jacket provides plenty of mobility and room to move on all your outdoor adventures.<a class="view-deal button" href="https://www.amazon.com/North-Face-Waterproof-Standard-Breathable/dp/B0D4SZT3ZM" target="_blank" rel="nofollow" data-dimension112="8440fe40-cc6e-11f1-b54b-b1964f093f7c" data-action="Deal Block" data-label="Antora Rain 2.0 Hooded Jacket (Women's)" data-dimension48="Antora Rain 2.0 Hooded Jacket (Women's)" data-dimension25="$110">View Deal</a></p></div><div class="product"><a data-dimension112="8440feea-cc6e-11f1-8fdd-6b0e3ea2adda" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$121" href="https://www.amazon.com/dp/B0CNBL2XXG" 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:187.78%;"><img id="jLN4YbW223nKsxQxPVPWZR" name="TNF jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jLN4YbW223nKsxQxPVPWZR-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1275" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0CNBL2XXG" target="_blank" rel="nofollow" data-dimension112="8440feea-cc6e-11f1-8fdd-6b0e3ea2adda" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$121">Aconcagua 3 Jacket (Men's): was $220 now $121</a></strong><br />This lightweight puffer blends recycled down with synthetic insulation for maximum warmth and weather resistance in a tidy, easy-to-stow package. Zonal sheet insulation and a water-repellant finish round out the feature set.<a class="view-deal button" href="https://www.amazon.com/dp/B0CNBL2XXG" target="_blank" rel="nofollow" data-dimension112="8440feea-cc6e-11f1-8fdd-6b0e3ea2adda" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$121">View Deal</a></p></div><h3 class="article-body__section" id="section-arc-teryx"><span>Arc'teryx</span></h3><div class="product"><a data-dimension112="84410020-cc6e-11f1-b0c3-19f894c87fe6" data-action="Deal Block" data-label="Sima Hoody (Men's)" data-dimension48="Sima Hoody (Men's)" data-dimension25="$119" href="https://www.rei.com/product/C01372/arcteryx-sima-hoody-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1999px;"><p class="vanilla-image-block" style="padding-top:100.05%;"><img id="7ALJ3myuTiT2XsP4zXyHWg" name="Arc'teryx Sima" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/7ALJ3myuTiT2XsP4zXyHWg-1920-80.jpg" mos="" align="middle" fullscreen="" width="1999" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01372/arcteryx-sima-hoody-mens" target="_blank" rel="nofollow" data-dimension112="84410020-cc6e-11f1-b0c3-19f894c87fe6" data-action="Deal Block" data-label="Sima Hoody (Men's)" data-dimension48="Sima Hoody (Men's)" data-dimension25="$119">Sima Hoody (Men's): was $160 now $119</a></strong><br />This chic zip-up jacket is designed with backpackers and hikers in mind. Weighing just over six ounces, it's made from synthetic fabric with UPF 50+ sun protection. Nice and breathable, the fabric is also moisture-wicking to keep you dry.<a class="view-deal button" href="https://www.rei.com/product/C01372/arcteryx-sima-hoody-mens" target="_blank" rel="nofollow" data-dimension112="84410020-cc6e-11f1-b0c3-19f894c87fe6" data-action="Deal Block" data-label="Sima Hoody (Men's)" data-dimension48="Sima Hoody (Men's)" data-dimension25="$119">View Deal</a></p></div><div class="product"><a data-dimension112="844100b6-cc6e-11f1-b6b4-1bff8a6769c0" data-action="Deal Block" data-label="Squamish Hoody (Men's)" data-dimension48="Squamish Hoody (Men's)" data-dimension25="$140" href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="gU2HZNV4QV8x48bVFDMoVL" name="Arc'teryx Squamish" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gU2HZNV4QV8x48bVFDMoVL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow" data-dimension112="844100b6-cc6e-11f1-b6b4-1bff8a6769c0" data-action="Deal Block" data-label="Squamish Hoody (Men's)" data-dimension48="Squamish Hoody (Men's)" data-dimension25="$140">Squamish Hoody (Men's): was $200 now $140</a></strong><br />The Arc'teryx Squamish Hoody is completely windproof and finished with DWR, making it a versatile outer layer for those nippy wintry hikes. There's even a capped hood for keeping your face dry.<a class="view-deal button" href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow" data-dimension112="844100b6-cc6e-11f1-b6b4-1bff8a6769c0" data-action="Deal Block" data-label="Squamish Hoody (Men's)" data-dimension48="Squamish Hoody (Men's)" data-dimension25="$140">View Deal</a></p></div><h3 class="article-body__section" id="section-adidas"><span>Adidas</span></h3><div class="product"><a data-dimension112="844101ec-cc6e-11f1-96a8-c3338539050f" data-action="Deal Block" data-label="Terrex Multi-Synthetic Insulated Hiking Jacket (Men's)" data-dimension48="Terrex Multi-Synthetic Insulated Hiking Jacket (Men's)" data-dimension25="$28" href="https://www.amazon.com/adidas-Standard-Multi-Synthetic-Insulated-Cardboard/dp/B0DJWNR8W6" 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:200.29%;"><img id="SkBUz9AdxzZ3oojsDsSiK8" name="Terrex Multi-Synthetic Insulated Hiking Jacket (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/SkBUz9AdxzZ3oojsDsSiK8-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1360" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/adidas-Standard-Multi-Synthetic-Insulated-Cardboard/dp/B0DJWNR8W6" target="_blank" rel="nofollow" data-dimension112="844101ec-cc6e-11f1-96a8-c3338539050f" data-action="Deal Block" data-label="Terrex Multi-Synthetic Insulated Hiking Jacket (Men's)" data-dimension48="Terrex Multi-Synthetic Insulated Hiking Jacket (Men's)" data-dimension25="$28">Terrex Multi-Synthetic Insulated Hiking Jacket (Men's): was $140 now $28</a></strong><br />I couldn't believe this 80% discount when I first saw it! This is a huge steal for an insulated hiking jacket. It's water-repellent to protect you from light rain and will keep you warm both on the trails and on casual walks.<a class="view-deal button" href="https://www.amazon.com/adidas-Standard-Multi-Synthetic-Insulated-Cardboard/dp/B0DJWNR8W6" target="_blank" rel="nofollow" data-dimension112="844101ec-cc6e-11f1-96a8-c3338539050f" data-action="Deal Block" data-label="Terrex Multi-Synthetic Insulated Hiking Jacket (Men's)" data-dimension48="Terrex Multi-Synthetic Insulated Hiking Jacket (Men's)" data-dimension25="$28">View Deal</a></p></div><div class="product"><a data-dimension112="8441028c-cc6e-11f1-a780-bb570b16e96e" data-action="Deal Block" data-label="All Szn Fleece Full-Zip Hoodie (Men's)" data-dimension48="All Szn Fleece Full-Zip Hoodie (Men's)" data-dimension25="$43" href="https://www.amazon.com/adidas-Fleece-Hoodie-Earth-Strata/dp/B0CMRRN52Q" 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:203.24%;"><img id="4Pr2wXN4KT6RTb89w7fzJb" name="7177i++ESRL._AC_SX679_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4Pr2wXN4KT6RTb89w7fzJb-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1380" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/adidas-Fleece-Hoodie-Earth-Strata/dp/B0CMRRN52Q" target="_blank" rel="nofollow" data-dimension112="8441028c-cc6e-11f1-a780-bb570b16e96e" data-action="Deal Block" data-label="All Szn Fleece Full-Zip Hoodie (Men's)" data-dimension48="All Szn Fleece Full-Zip Hoodie (Men's)" data-dimension25="$43">All Szn Fleece Full-Zip Hoodie (Men's): was $65 now $43</a></strong><br />This is one of my favorite items from Adidas' lineup. I'm a big fan of this hoodie's subtle Earth Strata colorway, and the loose fit means it's great for workouts or casual wear. Plus, like the name suggests, you can wear it all year round.<a class="view-deal button" href="https://www.amazon.com/adidas-Fleece-Hoodie-Earth-Strata/dp/B0CMRRN52Q" target="_blank" rel="nofollow" data-dimension112="8441028c-cc6e-11f1-a780-bb570b16e96e" data-action="Deal Block" data-label="All Szn Fleece Full-Zip Hoodie (Men's)" data-dimension48="All Szn Fleece Full-Zip Hoodie (Men's)" data-dimension25="$43">View Deal</a></p></div><h3 class="article-body__section" id="section-carhartt"><span>Carhartt</span></h3><div class="product"><a data-dimension112="221ce0e6-cc6c-11f1-841f-712b3b8b6ad4" data-action="Deal Block" data-label="Rain Defender Packable Anorak (Women's)" data-dimension48="Rain Defender Packable Anorak (Women's)" data-dimension25="$47" href="https://www.amazon.com/Carhartt-Defender-Lightweight-Packable-Asphalt/dp/B0BNJN3LDM" 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:221.80%;"><img id="W7hPuJg734Jg83fm9As5Qb" name="Carhartt rain jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/W7hPuJg734Jg83fm9As5Qb-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1506" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Carhartt-Defender-Lightweight-Packable-Asphalt/dp/B0BNJN3LDM" target="_blank" rel="nofollow" data-dimension112="221ce0e6-cc6c-11f1-841f-712b3b8b6ad4" data-action="Deal Block" data-label="Rain Defender Packable Anorak (Women's)" data-dimension48="Rain Defender Packable Anorak (Women's)" data-dimension25="$47">Rain Defender Packable Anorak (Women's): was $79 now $47</a></strong><br />The Rain Defender Anorak is a lightweight and packable water and wind-resistant half-zip with a large kangaroo-style velcro pocket up front and hidden zippered hand pockets along the side. The two-tone design gives off retro vibes while the roomy, loose-fit cut shouldn't restrict movement. <a class="view-deal button" href="https://www.amazon.com/Carhartt-Defender-Lightweight-Packable-Asphalt/dp/B0BNJN3LDM" target="_blank" rel="nofollow" data-dimension112="221ce0e6-cc6c-11f1-841f-712b3b8b6ad4" data-action="Deal Block" data-label="Rain Defender Packable Anorak (Women's)" data-dimension48="Rain Defender Packable Anorak (Women's)" data-dimension25="$47">View Deal</a></p></div><div class="product"><a data-dimension112="221ce140-cc6c-11f1-b9c1-ff5bd59d9332" data-action="Deal Block" data-label="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension48="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension25="$58" href="https://www.amazon.com/Carhartt-Relaxed-Full-Zip-Long-Sleeve-T-Shirt/dp/B0D3J857CC" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:594px;"><p class="vanilla-image-block" style="padding-top:168.18%;"><img id="XVAtjBrciTnPeT2AD3fLvm" name="Long Sleeve Full zip" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XVAtjBrciTnPeT2AD3fLvm-1920-80.jpg" mos="" align="middle" fullscreen="" width="594" height="999" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Carhartt-Relaxed-Full-Zip-Long-Sleeve-T-Shirt/dp/B0D3J857CC" target="_blank" rel="nofollow" data-dimension112="221ce140-cc6c-11f1-b9c1-ff5bd59d9332" data-action="Deal Block" data-label="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension48="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension25="$58">Force Relaxed Fit Full-Zip Long-Sleeve (Men's): was $84 now $58</a></strong><br />Perfect for a casual stroll, low-intensity workout or a longer run, this versatile layer features Carhartt Force technology to wick sweat, dry fast, and fight odors. It's a full zip and allows for a full range of motion too. <a class="view-deal button" href="https://www.amazon.com/Carhartt-Relaxed-Full-Zip-Long-Sleeve-T-Shirt/dp/B0D3J857CC" target="_blank" rel="nofollow" data-dimension112="221ce140-cc6c-11f1-b9c1-ff5bd59d9332" data-action="Deal Block" data-label="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension48="Force Relaxed Fit Full-Zip Long-Sleeve (Men's)" data-dimension25="$58">View Deal</a></p></div><div class="product"><a data-dimension112="221ce1a4-cc6c-11f1-87f5-4f1e36b02c49" data-action="Deal Block" data-label="Monterey Jacket (Women's)" data-dimension48="Monterey Jacket (Women's)" data-dimension25="$64" href="https://www.amazon.com/Carhartt-Womens-Defender-Lightweight-Packable/dp/B0F96WVJNC?" 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:201.18%;"><img id="WrHCmC5ZrvbsGGNpQnXLYL" name="Monterrey Jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/WrHCmC5ZrvbsGGNpQnXLYL-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1366" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Carhartt-Womens-Defender-Lightweight-Packable/dp/B0F96WVJNC?" target="_blank" rel="nofollow" data-dimension112="221ce1a4-cc6c-11f1-87f5-4f1e36b02c49" data-action="Deal Block" data-label="Monterey Jacket (Women's)" data-dimension48="Monterey Jacket (Women's)" data-dimension25="$64">Monterey Jacket (Women's): was $99 now $64</a></strong><br />Don't get caught in a rainstorm without this jacket. It features waterproof, breathable technology that stops water from getting in but lets sweat get out. It also has Wind Fighter technology to combat the elements. <a class="view-deal button" href="https://www.amazon.com/Carhartt-Womens-Defender-Lightweight-Packable/dp/B0F96WVJNC?" target="_blank" rel="nofollow" data-dimension112="221ce1a4-cc6c-11f1-87f5-4f1e36b02c49" data-action="Deal Block" data-label="Monterey Jacket (Women's)" data-dimension48="Monterey Jacket (Women's)" data-dimension25="$64">View Deal</a></p></div><div class="product"><a data-dimension112="221ce1fe-cc6c-11f1-919a-3beba15dc1c5" data-action="Deal Block" data-label="Rain Defender Jacket (Men's)" data-dimension48="Rain Defender Jacket (Men's)" data-dimension25="$74" href="https://www.amazon.com/Carhartt-Defender-Relaxed-Jacket-Ocean/dp/B0F8PP4JZ2" 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:127.84%;"><img id="VVpm8JrkWovdG4VCm3q4We" name="Rain Defender Jacket (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/VVpm8JrkWovdG4VCm3q4We-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="868" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Carhartt-Defender-Relaxed-Jacket-Ocean/dp/B0F8PP4JZ2" target="_blank" rel="nofollow" data-dimension112="221ce1fe-cc6c-11f1-919a-3beba15dc1c5" data-action="Deal Block" data-label="Rain Defender Jacket (Men's)" data-dimension48="Rain Defender Jacket (Men's)" data-dimension25="$74">Rain Defender Jacket (Men's): was $99 now $74</a></strong><br />The Carhartt Rain Defender Jacket is now on sale from $74. It's perfect to take on wind and rain, while keeping you warm and dry. It's durable and moves with you thanks to its Rugged Flex stretch technology.<a class="view-deal button" href="https://www.amazon.com/Carhartt-Defender-Relaxed-Jacket-Ocean/dp/B0F8PP4JZ2" target="_blank" rel="nofollow" data-dimension112="221ce1fe-cc6c-11f1-919a-3beba15dc1c5" data-action="Deal Block" data-label="Rain Defender Jacket (Men's)" data-dimension48="Rain Defender Jacket (Men's)" data-dimension25="$74">View Deal</a></p></div><h3 class="article-body__section" id="section-columbia"><span>Columbia</span></h3><div class="product"><a data-dimension112="221ce370-cc6c-11f1-96fb-d1bf87bef039" data-action="Deal Block" data-label="Switchback Jacket (Women's)" data-dimension48="Switchback Jacket (Women's)" data-dimension25="$37" href="https://www.amazon.com/dp/B0CLR14KFG?" 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:164.95%;"><img id="wS5fq4uyAmDFumApbN8rJR" name="Columbia Switchback" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/wS5fq4uyAmDFumApbN8rJR-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1120" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0CLR14KFG?" target="_blank" rel="nofollow" data-dimension112="221ce370-cc6c-11f1-96fb-d1bf87bef039" data-action="Deal Block" data-label="Switchback Jacket (Women's)" data-dimension48="Switchback Jacket (Women's)" data-dimension25="$37">Switchback Jacket (Women's): was $70 now $37</a></strong><br />This lightweight packable jacket takes up minimal real estate, so there's no excuse not to bring it along on your next outdoor outing. Plus, a hidden hood deploys from the collar when needed and a drawstring hem and adjustable cuffs ensure a watertight fit. <a class="view-deal button" href="https://www.amazon.com/dp/B0CLR14KFG?" target="_blank" rel="nofollow" data-dimension112="221ce370-cc6c-11f1-96fb-d1bf87bef039" data-action="Deal Block" data-label="Switchback Jacket (Women's)" data-dimension48="Switchback Jacket (Women's)" data-dimension25="$37">View Deal</a></p></div><div class="product"><a data-dimension112="221ce3ca-cc6c-11f1-98bd-71490c3642a7" data-action="Deal Block" data-label="Panorama Full Zip (Women's)" data-dimension48="Panorama Full Zip (Women's)" data-dimension25="$45" href="https://www.amazon.com/Columbia-Womens-Panorama-Moonvista-Large/dp/B0CLR9N5PW" 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:202.65%;"><img id="BmSeKyYnTe5vd4ghNKRCf8" name="columbia fleece" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/BmSeKyYnTe5vd4ghNKRCf8-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1376" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Columbia-Womens-Panorama-Moonvista-Large/dp/B0CLR9N5PW" target="_blank" rel="nofollow" data-dimension112="221ce3ca-cc6c-11f1-98bd-71490c3642a7" data-action="Deal Block" data-label="Panorama Full Zip (Women's)" data-dimension48="Panorama Full Zip (Women's)" data-dimension25="$45">Panorama Full Zip (Women's): was $100 now $45</a></strong><br />From a light hike to cozying up by the fire, this top-rated Sherpa fleece full zip that's lined with a soft, suede-like material, is perfect for all your outdoor adventures when the air is a bit crisp. It's cut with that classic style and fit you can count on.<a class="view-deal button" href="https://www.amazon.com/Columbia-Womens-Panorama-Moonvista-Large/dp/B0CLR9N5PW" target="_blank" rel="nofollow" data-dimension112="221ce3ca-cc6c-11f1-98bd-71490c3642a7" data-action="Deal Block" data-label="Panorama Full Zip (Women's)" data-dimension48="Panorama Full Zip (Women's)" data-dimension25="$45">View Deal</a></p></div><div class="product"><a data-dimension112="221ce424-cc6c-11f1-bd23-f3875692386f" data-action="Deal Block" data-label="Ascender Softshell Rain Jacket (Men's)" data-dimension48="Ascender Softshell Rain Jacket (Men's)" data-dimension25="$52" href="https://www.amazon.com/Columbia-Ascender-Softshell-Jacket-Black/dp/B0CLRBK7P2" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:829px;"><p class="vanilla-image-block" style="padding-top:100.12%;"><img id="RxbCzBdr6qyZyeYxwMo4jE" name="Columbia-m-ascender" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/RxbCzBdr6qyZyeYxwMo4jE-1920-80.jpg" mos="" align="middle" fullscreen="" width="829" height="830" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Columbia-Ascender-Softshell-Jacket-Black/dp/B0CLRBK7P2" target="_blank" rel="nofollow" data-dimension112="221ce424-cc6c-11f1-bd23-f3875692386f" data-action="Deal Block" data-label="Ascender Softshell Rain Jacket (Men's)" data-dimension48="Ascender Softshell Rain Jacket (Men's)" data-dimension25="$52">Ascender Softshell Rain Jacket (Men's): was $125 now $52</a></strong><br />This stretchy, chic softshell isn't for torrential downpours but will keep you dry in light rain and drizzle. Made from 100% polyester, it features zippered hand and chest pockets, an abrasion-resistant chin guard and an adjustable hem and cuffs. <a class="view-deal button" href="https://www.amazon.com/Columbia-Ascender-Softshell-Jacket-Black/dp/B0CLRBK7P2" target="_blank" rel="nofollow" data-dimension112="221ce424-cc6c-11f1-bd23-f3875692386f" data-action="Deal Block" data-label="Ascender Softshell Rain Jacket (Men's)" data-dimension48="Ascender Softshell Rain Jacket (Men's)" data-dimension25="$52">View Deal</a></p></div><div class="product"><a data-dimension112="221ce47e-cc6c-11f1-a39a-05e6a8c98b18" data-action="Deal Block" data-label="Women’s Kruser Ridge III Softshell Jacket" data-dimension48="Women’s Kruser Ridge III Softshell Jacket" data-dimension25="$87" href="https://www.amazon.com/Columbia-Womens-Kruser-Softshell-Jacket/dp/B0CLR7V452" 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:184.39%;"><img id="6Djt9vujjJqFV5FhisPWRc" name="61p6G9ZDclL._AC_SX679_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/6Djt9vujjJqFV5FhisPWRc-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1252" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Columbia-Womens-Kruser-Softshell-Jacket/dp/B0CLR7V452" target="_blank" rel="nofollow" data-dimension112="221ce47e-cc6c-11f1-a39a-05e6a8c98b18" data-action="Deal Block" data-label="Women’s Kruser Ridge III Softshell Jacket" data-dimension48="Women’s Kruser Ridge III Softshell Jacket" data-dimension25="$87">Women’s Kruser Ridge III Softshell Jacket: was $110 now $87</a></strong><br />A softshell jacket for $87? This is an amazing price for a water<em> and</em> rain-resistant shell that’ll keep you dry without getting overly sweaty as the weather changes. With large zipped pockets for your essentials and a drawcord hem to keep the cold out, this is a fantastic deal on a great jacket. <a class="view-deal button" href="https://www.amazon.com/Columbia-Womens-Kruser-Softshell-Jacket/dp/B0CLR7V452" target="_blank" rel="nofollow" data-dimension112="221ce47e-cc6c-11f1-a39a-05e6a8c98b18" data-action="Deal Block" data-label="Women’s Kruser Ridge III Softshell Jacket" data-dimension48="Women’s Kruser Ridge III Softshell Jacket" data-dimension25="$87">View Deal</a></p></div><div class="product"><a data-dimension112="221ce4e2-cc6c-11f1-862e-a5fbae305984" data-action="Deal Block" data-label="Powder Lite II Jacket (Men's)" data-dimension48="Powder Lite II Jacket (Men's)" data-dimension25="$115" href="https://www.amazon.com/Columbia-Powder-Jacket-Black-Large/dp/B0CLRBRZHS" 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:189.84%;"><img id="BtaCy7tDVwYLGzNAQeJusG" name="Powder Lite II Jacket (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/BtaCy7tDVwYLGzNAQeJusG-1920-80.jpg" mos="" align="middle" fullscreen="" width="679" height="1289" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Columbia-Powder-Jacket-Black-Large/dp/B0CLRBRZHS" target="_blank" rel="nofollow" data-dimension112="221ce4e2-cc6c-11f1-862e-a5fbae305984" data-action="Deal Block" data-label="Powder Lite II Jacket (Men's)" data-dimension48="Powder Lite II Jacket (Men's)" data-dimension25="$115">Powder Lite II Jacket (Men's): was $165 now $115</a></strong><br />Columbia’s Omni-Heat thermal-reflective lining retains your body's own warmth, and the puffer also has a water-resistant outer layer for wet weather. Plus, it stows easily and is super lightweight if you enjoy hiking.<a class="view-deal button" href="https://www.amazon.com/Columbia-Powder-Jacket-Black-Large/dp/B0CLRBRZHS" target="_blank" rel="nofollow" data-dimension112="221ce4e2-cc6c-11f1-862e-a5fbae305984" data-action="Deal Block" data-label="Powder Lite II Jacket (Men's)" data-dimension48="Powder Lite II Jacket (Men's)" data-dimension25="$115">View Deal</a></p></div><h3 class="article-body__section" id="section-under-armour"><span>Under Armour</span></h3><div class="product"><a data-dimension112="221ce870-cc6c-11f1-aae4-213d2af84719" data-action="Deal Block" data-label="Motion Jacket (Women's)" data-dimension48="Motion Jacket (Women's)" data-dimension25="$36" href="https://www.amazon.com/Under-Armour-Womens-Motion-Jacket/dp/B08LN1MLQS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:433px;"><p class="vanilla-image-block" style="padding-top:230.95%;"><img id="CmtEvXMpkpp7SbDcxDYzY9" name="Motion Jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/CmtEvXMpkpp7SbDcxDYzY9-1920-80.jpg" mos="" align="middle" fullscreen="" width="433" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Under-Armour-Womens-Motion-Jacket/dp/B08LN1MLQS" target="_blank" rel="nofollow" data-dimension112="221ce870-cc6c-11f1-aae4-213d2af84719" data-action="Deal Block" data-label="Motion Jacket (Women's)" data-dimension48="Motion Jacket (Women's)" data-dimension25="$36">Motion Jacket (Women's): was $55 now $36</a></strong><br />This stylish jacket is made of ultra soft fabric that is both breathable and comfortable. Similar to the flare pants above, it features four-way stretch material that helps you move in any direction.<a class="view-deal button" href="https://www.amazon.com/Under-Armour-Womens-Motion-Jacket/dp/B08LN1MLQS" target="_blank" rel="nofollow" data-dimension112="221ce870-cc6c-11f1-aae4-213d2af84719" data-action="Deal Block" data-label="Motion Jacket (Women's)" data-dimension48="Motion Jacket (Women's)" data-dimension25="$36">View Deal</a></p></div><div class="product"><a data-dimension112="221ce924-cc6c-11f1-8f1d-21687bef681b" data-action="Deal Block" data-label="Rival Woven Windbreaker (Men's)" data-dimension48="Rival Woven Windbreaker (Men's)" data-dimension25="$50" href="https://www.amazon.com/Under-Armour-Rival-Windbreaker-Medium/dp/B0D1669X2T" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:442px;"><p class="vanilla-image-block" style="padding-top:167.65%;"><img id="6L4HJj86LoQsb7ZXGJJ2eR" name="Rival Woven Windbreaker (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/6L4HJj86LoQsb7ZXGJJ2eR-1920-80.jpg" mos="" align="middle" fullscreen="" width="442" height="741" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Under-Armour-Rival-Windbreaker-Medium/dp/B0D1669X2T" target="_blank" rel="nofollow" data-dimension112="221ce924-cc6c-11f1-8f1d-21687bef681b" data-action="Deal Block" data-label="Rival Woven Windbreaker (Men's)" data-dimension48="Rival Woven Windbreaker (Men's)" data-dimension25="$50">Rival Woven Windbreaker (Men's): was $65 now $50</a></strong><br />This Under Armour windbreaker will make wind the least of your worries. It's breathable, while keeping out light wind and rain, and has a lightweight feel.<a class="view-deal button" href="https://www.amazon.com/Under-Armour-Rival-Windbreaker-Medium/dp/B0D1669X2T" target="_blank" rel="nofollow" data-dimension112="221ce924-cc6c-11f1-8f1d-21687bef681b" data-action="Deal Block" data-label="Rival Woven Windbreaker (Men's)" data-dimension48="Rival Woven Windbreaker (Men's)" data-dimension25="$50">View Deal</a></p></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 3 anti-aging strength exercises everyone over 40 should do every week ]]></title>
                                                                                                <dc:content><![CDATA[ <p>After the age of 40, we naturally start to lose muscle mass. One of the best ways to prevent this is to strength train — it counters sarcopenia, maintains muscle mass and protects your bones. Yet if you’re a complete beginner, or you’re returning to fitness following an extended break, it can be tricky to know where to start. Luckily, you’ve landed in the right place, as below, our resident personal trainer Sam Hopes has shared three anti-aging strength exercises everyone over 40 should be doing. </p><p>As a reminder, if you’re currently recovering from an injury or surgery, these might not be the right exercises for you and your body. It’s always best to seek personalized advice from a qualified professional before trying something new. </p><h2 id="3-anti-aging-strength-exercises-everyone-over-40-should-do-every-week">3 anti-aging strength exercises everyone over 40 should do every week</h2><p>The three exercises below target all of the major muscle groups in the body. You can do them all with just your bodyweight, but using a set of the <a href="https://www.tomsguide.com/wellness/fitness/best-adjustable-dumbbells">best adjustable dumbbells</a> to increase the resistance is a great way to increase the load on your body as you move. </p><p>Remember, the right weight should feel challenging, but not impossible by the final few reps. If at any time you feel like the weight is compromising your form, it’s too heavy, and you should drop down to a lighter set of dumbbells. </p><h3 class="article-body__section" id="section-1-bulgarian-split-squats"><span>1. Bulgarian split squats </span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="wKPMvt6mXie2sn2tbJn6pe" name="bulgarian split squat.jpg" alt="an illo of a man doing a bulgarian split squat" src="https://cdn.mos.cms.futurecdn.net/wKPMvt6mXie2sn2tbJn6pe-1920-80.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><strong>Why</strong>: The Bulgarian split squat is a fantastic functional lower-body exercise. You’re working one leg at a time, which can help you fix muscle imbalances in the body. Over time, an imbalance can lead to hip or knee injuries, so this is a good one to address. </p><p>Compared to traditional squats, the Bulgarian split squat challenges the quads and glutes using a light set of dumbbells or your bodyweight alone. Elevating the back foot forces the glutes, ankles, and core to engage, as well as stretching out tight hip flexors.</p><p>Sam recommends holding a dumbbell in the opposite hand to the leg that’s working (the front leg).</p><p><strong>How</strong>:  </p><ul><li>To get in the right position, start by sitting in front of a bench or box and extend one leg out in front of you, then stand up. That front foot is your marker.</li><li>Lift the back foot up and place the top of your non-working foot on the bench. Your feet should be about hip-distance apart.</li><li>Hold a dumbbell in the opposite hand to your front leg (in other words, on the same side as the lifted leg).</li><li>Engage your core, thinking about sucking your belly button into your spine, and keep your chest open.</li><li>Bend your front knee and hip, lowering your back knee down towards the floor.</li><li>Push through the heel of your front foot to return to your starting position.</li></ul><p>Do all of your reps on one side before switching to the other. Aim for 10 reps on each side. If you’re a complete beginner, start with the bodyweight variation of this move first. </p><h3 class="article-body__section" id="section-2-deadlift"><span>2. Deadlift </span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Zxnfi3psGuegMYsCBYcoeZ" name="dumbbell deadlift" alt="a man doing a dumbbell deadlift" src="https://cdn.mos.cms.futurecdn.net/Zxnfi3psGuegMYsCBYcoeZ-1920-80.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><strong>Why</strong>: The deadlift is another fantastic functional move that targets the glutes, hamstrings, erector spinae, and upper back. It mimics a movement pattern you’ll make every day as you bend down to pick up groceries or move furniture. It can also help build bone density in the spine and hips — two sites that are vulnerable to osteoporotic fractures.</p><p><strong>How</strong>:</p><ul><li>Dumbbell deadlifts are the best variation to start with, as they keep the load closer to your body’s center of gravity. Start by holding a dumbbell in each hand and standing with your feet hip-distance apart.</li><li>Engage your core, thinking about sucking your belly button into your spine. Pull your shoulders down and back away from your ears.</li><li>Hinge at your hips and push your hips back behind you, allowing your upper body to tilt forward. Keep your back flat and your neck neutral, looking down at the floor rather than out in front of you.</li><li>Once your hands pass your knees, bend your knees slightly to lower the dumbbells towards the mid-shins. Keep the weights close to your legs.</li><li>Drive through your heels to stand back up. Squeeze your glutes firmly at the top.</li></ul><h3 class="article-body__section" id="section-3-push-up"><span>3. Push-up</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="CoW5h97B3pQDW6fGTXm23W" name="how to do a push up.jpg" alt="a photo fo a woman doing a push up" src="https://cdn.mos.cms.futurecdn.net/CoW5h97B3pQDW6fGTXm23W-1920-80.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><strong>Why</strong>: Push-ups are a great, joint-friendly way to work the upper body. You’ll build functional mobility and core strength without putting a heavy load on your shoulders. You’ll also be working on preserving bone density in your wrists, elbows, shoulders and chest bones.</p><p><strong>How</strong>: </p><ul><li>If you’re a beginner, you might want to do a variation with your knees resting on the floor, but let's start with how to do a full push-up.</li><li>Start by placing your hands slightly wider than shoulder-width apart, spreading your fingers wide for stability.</li><li>Extend your legs behind you with your feet hip-width apart. Squeeze your glutes and brace your core, squeezing your belly button in towards your spine. Your body should form a straight line from your head to your heels.</li><li>Keep your elbows tucked at a 45-degree angle to your torso rather than letting them flare out to the side.</li><li>Inhale as you bend your elbows and slowly lower your chest until it skims the floor.</li><li>Exhale as you push firmly through your palms to return to your starting position, fully extending your arms.</li></ul><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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/i-teach-people-how-to-be-strong-and-mobile-this-is-the-one-exercise-i-regret-ignoring-for-years" target="_blank">I teach people how to be strong and mobile: this is the one exercise I regret ignoring for years</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><strong></strong></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/workouts/3-anti-aging-strength-exercises-everyone-over-40-should-do-every-week</link>
                                                                            <description>
                            <![CDATA[ Here are the three exercises you should be doing, according to our resident personal trainer ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">m8eTc9HLEFht2wP6sDVAjE</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/A2MxwQ7pSsNSye8RpbLngX-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Tue, 20 Oct 2026 08: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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/A2MxwQ7pSsNSye8RpbLngX-1920-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a woman doing a push up on her knees ]]></media:description>                                                            <media:text><![CDATA[a woman doing a push up on her knees ]]></media:text>
                                <media:title type="plain"><![CDATA[a woman doing a push up on her knees ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/A2MxwQ7pSsNSye8RpbLngX-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>After the age of 40, we naturally start to lose muscle mass. One of the best ways to prevent this is to strength train — it counters sarcopenia, maintains muscle mass and protects your bones. Yet if you’re a complete beginner, or you’re returning to fitness following an extended break, it can be tricky to know where to start. Luckily, you’ve landed in the right place, as below, our resident personal trainer Sam Hopes has shared three anti-aging strength exercises everyone over 40 should be doing. </p><p>As a reminder, if you’re currently recovering from an injury or surgery, these might not be the right exercises for you and your body. It’s always best to seek personalized advice from a qualified professional before trying something new. </p><h2 id="3-anti-aging-strength-exercises-everyone-over-40-should-do-every-week">3 anti-aging strength exercises everyone over 40 should do every week</h2><p>The three exercises below target all of the major muscle groups in the body. You can do them all with just your bodyweight, but using a set of the <a href="https://www.tomsguide.com/wellness/fitness/best-adjustable-dumbbells">best adjustable dumbbells</a> to increase the resistance is a great way to increase the load on your body as you move. </p><p>Remember, the right weight should feel challenging, but not impossible by the final few reps. If at any time you feel like the weight is compromising your form, it’s too heavy, and you should drop down to a lighter set of dumbbells. </p><h3 class="article-body__section" id="section-1-bulgarian-split-squats"><span>1. Bulgarian split squats </span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="wKPMvt6mXie2sn2tbJn6pe" name="bulgarian split squat.jpg" alt="an illo of a man doing a bulgarian split squat" src="https://cdn.mos.cms.futurecdn.net/wKPMvt6mXie2sn2tbJn6pe-1920-80.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><strong>Why</strong>: The Bulgarian split squat is a fantastic functional lower-body exercise. You’re working one leg at a time, which can help you fix muscle imbalances in the body. Over time, an imbalance can lead to hip or knee injuries, so this is a good one to address. </p><p>Compared to traditional squats, the Bulgarian split squat challenges the quads and glutes using a light set of dumbbells or your bodyweight alone. Elevating the back foot forces the glutes, ankles, and core to engage, as well as stretching out tight hip flexors.</p><p>Sam recommends holding a dumbbell in the opposite hand to the leg that’s working (the front leg).</p><p><strong>How</strong>:  </p><ul><li>To get in the right position, start by sitting in front of a bench or box and extend one leg out in front of you, then stand up. That front foot is your marker.</li><li>Lift the back foot up and place the top of your non-working foot on the bench. Your feet should be about hip-distance apart.</li><li>Hold a dumbbell in the opposite hand to your front leg (in other words, on the same side as the lifted leg).</li><li>Engage your core, thinking about sucking your belly button into your spine, and keep your chest open.</li><li>Bend your front knee and hip, lowering your back knee down towards the floor.</li><li>Push through the heel of your front foot to return to your starting position.</li></ul><p>Do all of your reps on one side before switching to the other. Aim for 10 reps on each side. If you’re a complete beginner, start with the bodyweight variation of this move first. </p><h3 class="article-body__section" id="section-2-deadlift"><span>2. Deadlift </span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="Zxnfi3psGuegMYsCBYcoeZ" name="dumbbell deadlift" alt="a man doing a dumbbell deadlift" src="https://cdn.mos.cms.futurecdn.net/Zxnfi3psGuegMYsCBYcoeZ-1920-80.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><strong>Why</strong>: The deadlift is another fantastic functional move that targets the glutes, hamstrings, erector spinae, and upper back. It mimics a movement pattern you’ll make every day as you bend down to pick up groceries or move furniture. It can also help build bone density in the spine and hips — two sites that are vulnerable to osteoporotic fractures.</p><p><strong>How</strong>:</p><ul><li>Dumbbell deadlifts are the best variation to start with, as they keep the load closer to your body’s center of gravity. Start by holding a dumbbell in each hand and standing with your feet hip-distance apart.</li><li>Engage your core, thinking about sucking your belly button into your spine. Pull your shoulders down and back away from your ears.</li><li>Hinge at your hips and push your hips back behind you, allowing your upper body to tilt forward. Keep your back flat and your neck neutral, looking down at the floor rather than out in front of you.</li><li>Once your hands pass your knees, bend your knees slightly to lower the dumbbells towards the mid-shins. Keep the weights close to your legs.</li><li>Drive through your heels to stand back up. Squeeze your glutes firmly at the top.</li></ul><h3 class="article-body__section" id="section-3-push-up"><span>3. Push-up</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="CoW5h97B3pQDW6fGTXm23W" name="how to do a push up.jpg" alt="a photo fo a woman doing a push up" src="https://cdn.mos.cms.futurecdn.net/CoW5h97B3pQDW6fGTXm23W-1920-80.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><strong>Why</strong>: Push-ups are a great, joint-friendly way to work the upper body. You’ll build functional mobility and core strength without putting a heavy load on your shoulders. You’ll also be working on preserving bone density in your wrists, elbows, shoulders and chest bones.</p><p><strong>How</strong>: </p><ul><li>If you’re a beginner, you might want to do a variation with your knees resting on the floor, but let's start with how to do a full push-up.</li><li>Start by placing your hands slightly wider than shoulder-width apart, spreading your fingers wide for stability.</li><li>Extend your legs behind you with your feet hip-width apart. Squeeze your glutes and brace your core, squeezing your belly button in towards your spine. Your body should form a straight line from your head to your heels.</li><li>Keep your elbows tucked at a 45-degree angle to your torso rather than letting them flare out to the side.</li><li>Inhale as you bend your elbows and slowly lower your chest until it skims the floor.</li><li>Exhale as you push firmly through your palms to return to your starting position, fully extending your arms.</li></ul><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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/i-teach-people-how-to-be-strong-and-mobile-this-is-the-one-exercise-i-regret-ignoring-for-years" target="_blank">I teach people how to be strong and mobile: this is the one exercise I regret ignoring for years</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><strong></strong></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ Lululemon just restocked its ‘We Made Too Much’ section — here are 9 fall finds under $100 ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Ready to refresh your fitness wardrobe for fall? Lululemon has you covered, whether you’re looking for new gym essentials or a cozy sweatshirt to keep you warm as the temperatures drop.</p><p>In fact, <a href="https://shop.lululemon.com/c/we-made-too-much/n18mhd" target="_blank" rel="nofollow">the brand recently restocked its 'We Made Too Much' section</a>. I did some digging and found a ton of great styles that are under $100. If you're looking to stock up on affordable fitness pieces, keep scrolling to check out my favorite picks for fall. </p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><a href="https://shop.lululemon.com/c/we-made-too-much/n18mhd" target="_blank" rel="nofollow"><strong>shop Lululemon's 'We Made Too Much' section</strong></a></li><li><strong>Align Tank Top (Women's): </strong><a href="https://shop.lululemon.com/p/align-tank/mnt6w420dl?color=77007" target="_blank" rel="nofollow"><strong>was $68 now $49</strong></a></li><li><strong>Swiftly Tech Long-Sleeve Shirt 2.0: </strong><a href="https://shop.lululemon.com/p/swiftly-tech-ls-2-race/o7l7jc0lss?color=79549" target="_blank" rel="nofollow"><strong>was $78 now $54</strong></a></li><li><strong>Align High-Rise Pant 28": </strong><a href="https://shop.lululemon.com/p/align-pant-full-length-28/vggwe5mu1w?color=77007" target="_blank" rel="nofollow"><strong>was $98 now $69</strong></a></li><li><strong>BeCalm Mid-Rise Wide-Leg Pant: </strong><a href="https://shop.lululemon.com/p/becalm-mid-rise-wide-leg-pant/fx7b5sldlb?color=33454" target="_blank" rel="nofollow"><strong>was $98 now $59</strong></a></li><li><strong>Define Cropped Nulu Jacket: </strong><a href="https://shop.lululemon.com/p/nulu-cropped-define-jacket/oo2vz3qc01?color=77066&amp;sz=4" target="_blank" rel="nofollow"><strong>was $128 now $99</strong></a></li></ul><h3 class="article-body__section" id="section-lululemon-deals"><span>Lululemon Deals</span></h3><div class="product"><a data-dimension112="4b47b0a2-cbce-11f1-9267-3393ab76c93e" data-action="Deal Block" data-label="Dual Pouch Wristlet" data-dimension48="Dual Pouch Wristlet" data-dimension25="$39" href="https://shop.lululemon.com/p/dual-pouch-wristlet/cicnujjsok?color=76797" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1440px;"><p class="vanilla-image-block" style="padding-top:120.00%;"><img id="jYPKTpKt3PdciCh2M8kquJ" name="Wristlet" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jYPKTpKt3PdciCh2M8kquJ-1920-80.jpg" mos="" align="middle" fullscreen="" width="1440" height="1728" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/dual-pouch-wristlet/cicnujjsok?color=76797" target="_blank" rel="nofollow" data-dimension112="4b47b0a2-cbce-11f1-9267-3393ab76c93e" data-action="Deal Block" data-label="Dual Pouch Wristlet" data-dimension48="Dual Pouch Wristlet" data-dimension25="$39">Dual Pouch Wristlet: was $48 now $39</a></strong><br />This cute wristlet keeps all your small items in place while you're on the move. It comes with two zippered pouches and will have you ready to go in the flick of a wrist. <a class="view-deal button" href="https://shop.lululemon.com/p/dual-pouch-wristlet/cicnujjsok?color=76797" target="_blank" rel="nofollow" data-dimension112="4b47b0a2-cbce-11f1-9267-3393ab76c93e" data-action="Deal Block" data-label="Dual Pouch Wristlet" data-dimension48="Dual Pouch Wristlet" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="4b47b16a-cbce-11f1-9c69-3f3e23e4cb22" data-action="Deal Block" data-label="Mesh Soft Jersey Short-Sleeve Shirt (Men's)" data-dimension48="Mesh Soft Jersey Short-Sleeve Shirt (Men's)" data-dimension25="$44" href="https://shop.lululemon.com/p/mesh-soft-jersey-short-sleeve-shirt/b3nwac6tbb?color=0001" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:120.00%;"><img id="sNvV6WjjMp69XVcKVzp7DM" name="long sleeve shirt" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sNvV6WjjMp69XVcKVzp7DM-1920-80.jpg" mos="" align="middle" fullscreen="" width="1800" height="2160" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/mesh-soft-jersey-short-sleeve-shirt/b3nwac6tbb?color=0001" target="_blank" rel="nofollow" data-dimension112="4b47b16a-cbce-11f1-9c69-3f3e23e4cb22" data-action="Deal Block" data-label="Mesh Soft Jersey Short-Sleeve Shirt (Men's)" data-dimension48="Mesh Soft Jersey Short-Sleeve Shirt (Men's)" data-dimension25="$44">Mesh Soft Jersey Short-Sleeve Shirt (Men's): was $58 now $44</a></strong><br />This is the ultimate training tee you've been looking for. It's made with a lightweight material that feels cozy against the skin, yet looks stylish enough to wear for a night out. As a bonus, this shirt's fabric features quick-drying and sweat-wicking material. <a class="view-deal button" href="https://shop.lululemon.com/p/mesh-soft-jersey-short-sleeve-shirt/b3nwac6tbb?color=0001" target="_blank" rel="nofollow" data-dimension112="4b47b16a-cbce-11f1-9c69-3f3e23e4cb22" data-action="Deal Block" data-label="Mesh Soft Jersey Short-Sleeve Shirt (Men's)" data-dimension48="Mesh Soft Jersey Short-Sleeve Shirt (Men's)" data-dimension25="$44">View Deal</a></p></div><div class="product"><a data-dimension112="4b47b106-cbce-11f1-b97e-affda28134f6" data-action="Deal Block" data-label="Align Tank Top (Women's)" data-dimension48="Align Tank Top (Women's)" data-dimension25="$49" href="https://shop.lululemon.com/p/align-tank/mnt6w420dl?color=77007" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:120.00%;"><img id="bKRE3xAww39376wSTqb4ah" name="lululemon Align" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bKRE3xAww39376wSTqb4ah-1920-80.jpg" mos="" align="middle" fullscreen="" width="1800" height="2160" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/align-tank/mnt6w420dl?color=77007" target="_blank" rel="nofollow" data-dimension112="4b47b106-cbce-11f1-b97e-affda28134f6" data-action="Deal Block" data-label="Align Tank Top (Women's)" data-dimension48="Align Tank Top (Women's)" data-dimension25="$49">Align Tank Top (Women's): was $68 now $49</a></strong><br />This super-soft, super-comfortable tank top has a built-in bra for light support during hikes, Pilates, and yoga classes. It’s soft and sweat-wicking and comes in several different colorways to suit every style. It’s also slightly cropped to allow you to move through different yoga poses. <a class="view-deal button" href="https://shop.lululemon.com/p/align-tank/mnt6w420dl?color=77007" target="_blank" rel="nofollow" data-dimension112="4b47b106-cbce-11f1-b97e-affda28134f6" data-action="Deal Block" data-label="Align Tank Top (Women's)" data-dimension48="Align Tank Top (Women's)" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="4b47b1ce-cbce-11f1-86e6-9d37f07a968f" data-action="Deal Block" data-label="Swiftly Tech Long-Sleeve Shirt 2.0 Waist Length (Women's)" data-dimension48="Swiftly Tech Long-Sleeve Shirt 2.0 Waist Length (Women's)" data-dimension25="$54" href="https://shop.lululemon.com/p/tops-long-sleeve/Swiftly-Tech-LS-2-Race-MD/_/prod9820340?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:120.00%;"><img id="XoSWXGqQwcoKgthBaaupyn" name="long sleeve" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XoSWXGqQwcoKgthBaaupyn-1920-80.jpg" mos="" align="middle" fullscreen="" width="1800" height="2160" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/tops-long-sleeve/Swiftly-Tech-LS-2-Race-MD/_/prod9820340?" target="_blank" rel="nofollow" data-dimension112="4b47b1ce-cbce-11f1-86e6-9d37f07a968f" data-action="Deal Block" data-label="Swiftly Tech Long-Sleeve Shirt 2.0 Waist Length (Women's)" data-dimension48="Swiftly Tech Long-Sleeve Shirt 2.0 Waist Length (Women's)" data-dimension25="$54">Swiftly Tech Long-Sleeve Shirt 2.0 Waist Length (Women's): was $78 now $54</a></strong><br />This is the perfect layer to have in your wardrobe. The swiftly tech tops have been a Lululemon staple for decades, and you can wear (and wash) them again and again without them going smelly or shrinking. <a class="view-deal button" href="https://shop.lululemon.com/p/tops-long-sleeve/Swiftly-Tech-LS-2-Race-MD/_/prod9820340?" target="_blank" rel="nofollow" data-dimension112="4b47b1ce-cbce-11f1-86e6-9d37f07a968f" data-action="Deal Block" data-label="Swiftly Tech Long-Sleeve Shirt 2.0 Waist Length (Women's)" data-dimension48="Swiftly Tech Long-Sleeve Shirt 2.0 Waist Length (Women's)" data-dimension25="$54">View Deal</a></p></div><div class="product"><a data-dimension112="4b47b296-cbce-11f1-aa82-f7ef03357455" data-action="Deal Block" data-label="BeCalm Mid-Rise Wide-Leg Pant (Women's)" data-dimension48="BeCalm Mid-Rise Wide-Leg Pant (Women's)" data-dimension25="$59" href="https://shop.lululemon.com/p/becalm-mid-rise-wide-leg-pant/fx7b5sldlb?color=33454" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1440px;"><p class="vanilla-image-block" style="padding-top:120.00%;"><img id="ZpgP85PS6xp6USEEmqD8om" name="lululemon pant" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZpgP85PS6xp6USEEmqD8om-1920-80.jpg" mos="" align="middle" fullscreen="" width="1440" height="1728" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/becalm-mid-rise-wide-leg-pant/fx7b5sldlb?color=33454" target="_blank" rel="nofollow" data-dimension112="4b47b296-cbce-11f1-aa82-f7ef03357455" data-action="Deal Block" data-label="BeCalm Mid-Rise Wide-Leg Pant (Women's)" data-dimension48="BeCalm Mid-Rise Wide-Leg Pant (Women's)" data-dimension25="$59">BeCalm Mid-Rise Wide-Leg Pant (Women's): was $98 now $59</a></strong><br />These pants are luxuriously comfortable, making them great for couch surfing, but have a chic and smart look that works on days out too. They're made with French terry and are soft to the touch. I need pants that do both, so I feel like these are a smart choice.<a class="view-deal button" href="https://shop.lululemon.com/p/becalm-mid-rise-wide-leg-pant/fx7b5sldlb?color=33454" target="_blank" rel="nofollow" data-dimension112="4b47b296-cbce-11f1-aa82-f7ef03357455" data-action="Deal Block" data-label="BeCalm Mid-Rise Wide-Leg Pant (Women's)" data-dimension48="BeCalm Mid-Rise Wide-Leg Pant (Women's)" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="4b47b228-cbce-11f1-b72a-b5f887c49ee4" data-action="Deal Block" data-label="Align High-Rise Pant 28" (Women's)" data-dimension48="Align High-Rise Pant 28" (Women's)" data-dimension25="$69" href="https://shop.lululemon.com/p/align-pant-full-length-28/vggwe5mu1w?color=77007" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:120.00%;"><img id="MiCGD28QzTaN9eQYAiWe3Q" name="lululemon high rise" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/MiCGD28QzTaN9eQYAiWe3Q-1920-80.jpg" mos="" align="middle" fullscreen="" width="1800" height="2160" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/align-pant-full-length-28/vggwe5mu1w?color=77007" target="_blank" rel="nofollow" data-dimension112="4b47b228-cbce-11f1-b72a-b5f887c49ee4" data-action="Deal Block" data-label="Align High-Rise Pant 28" (Women's)" data-dimension48="Align High-Rise Pant 28" (Women's)" data-dimension25="$69">Align High-Rise Pant 28" (Women's): was $98 now $69</a></strong><br />On sale from $69, the popular Align leggings are a great buy. We love these due to their comfortable, sculpted fit,  and extremely soft fabric. They also stretch with you and wick sweat while you're working out.<a class="view-deal button" href="https://shop.lululemon.com/p/align-pant-full-length-28/vggwe5mu1w?color=77007" target="_blank" rel="nofollow" data-dimension112="4b47b228-cbce-11f1-b72a-b5f887c49ee4" data-action="Deal Block" data-label="Align High-Rise Pant 28" (Women's)" data-dimension48="Align High-Rise Pant 28" (Women's)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="4b47b2f0-cbce-11f1-aeb6-27d3b3cb8e54" data-action="Deal Block" data-label="Scuba Evolve Oversized Half-Zip Hoodie (Women's)" data-dimension48="Scuba Evolve Oversized Half-Zip Hoodie (Women's)" data-dimension25="$94" href="https://shop.lululemon.com/p/scuba-evolve-oversized-half-zip-hoodie/lp4yqrz3sp?color=76925" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:119.94%;"><img id="i5m2KDsgHt4RywbcyUmMRk" name="scuba evolve" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/i5m2KDsgHt4RywbcyUmMRk-1920-80.jpg" mos="" align="middle" fullscreen="" width="1800" height="2159" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/scuba-evolve-oversized-half-zip-hoodie/lp4yqrz3sp?color=76925" target="_blank" rel="nofollow" data-dimension112="4b47b2f0-cbce-11f1-aeb6-27d3b3cb8e54" data-action="Deal Block" data-label="Scuba Evolve Oversized Half-Zip Hoodie (Women's)" data-dimension48="Scuba Evolve Oversized Half-Zip Hoodie (Women's)" data-dimension25="$94">Scuba Evolve Oversized Half-Zip Hoodie (Women's): was $128 now $94</a></strong><br />This half-zip scuba hoodie exudes comfortability. It's made with a plush, cotton-blend fleece fabric that's naturally breathable and insanely soft against the skin. Then, the oversized fit is perfect for throwing over a sports bra on your way to the gym or for reaching maximum coziness at home.<a class="view-deal button" href="https://shop.lululemon.com/p/scuba-evolve-oversized-half-zip-hoodie/lp4yqrz3sp?color=76925" target="_blank" rel="nofollow" data-dimension112="4b47b2f0-cbce-11f1-aeb6-27d3b3cb8e54" data-action="Deal Block" data-label="Scuba Evolve Oversized Half-Zip Hoodie (Women's)" data-dimension48="Scuba Evolve Oversized Half-Zip Hoodie (Women's)" data-dimension25="$94">View Deal</a></p></div><div class="product"><a data-dimension112="4b47b354-cbce-11f1-95cb-a9406c5ab5f1" data-action="Deal Block" data-label="Define Cropped Nulu Jacket (Women's)" data-dimension48="Define Cropped Nulu Jacket (Women's)" data-dimension25="$99" href="https://shop.lululemon.com/p/nulu-cropped-define-jacket/oo2vz3qc01?color=77584" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:120.00%;"><img id="4DSvzmsKSiPsZWmTobcmz5" name="nulu jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4DSvzmsKSiPsZWmTobcmz5-1920-80.jpg" mos="" align="middle" fullscreen="" width="1800" height="2160" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/nulu-cropped-define-jacket/oo2vz3qc01?color=77584" target="_blank" rel="nofollow" data-dimension112="4b47b354-cbce-11f1-95cb-a9406c5ab5f1" data-action="Deal Block" data-label="Define Cropped Nulu Jacket (Women's)" data-dimension48="Define Cropped Nulu Jacket (Women's)" data-dimension25="$99">Define Cropped Nulu Jacket (Women's): was $128 now $99</a></strong><br />Made from Lululemon’s famously buttery-soft Nulu fabric, this lightweight jacket is perfect for throwing on over workout gear. It pairs nicely with high-rise leggings, biker shorts or trousers and comes with zippered pockets and thumbholes to stop sleeves riding up mid-workout.<a class="view-deal button" href="https://shop.lululemon.com/p/nulu-cropped-define-jacket/oo2vz3qc01?color=77584" target="_blank" rel="nofollow" data-dimension112="4b47b354-cbce-11f1-95cb-a9406c5ab5f1" data-action="Deal Block" data-label="Define Cropped Nulu Jacket (Women's)" data-dimension48="Define Cropped Nulu Jacket (Women's)" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="4b47b3b8-cbce-11f1-ba0e-a77537f93232" data-action="Deal Block" data-label="Ease The Day Half Zip (Men's)" data-dimension48="Ease The Day Half Zip (Men's)" data-dimension25="$99" href="https://shop.lululemon.com/p/ease-the-day-half-zip/h0x4mw5adm?color=80675" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:120.00%;"><img id="ZjAAUq5gXJx9ert8yRZG6Z" name="half zip" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZjAAUq5gXJx9ert8yRZG6Z-1920-80.jpg" mos="" align="middle" fullscreen="" width="1800" height="2160" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/ease-the-day-half-zip/h0x4mw5adm?color=80675" target="_blank" rel="nofollow" data-dimension112="4b47b3b8-cbce-11f1-ba0e-a77537f93232" data-action="Deal Block" data-label="Ease The Day Half Zip (Men's)" data-dimension48="Ease The Day Half Zip (Men's)" data-dimension25="$99">Ease The Day Half Zip (Men's): was $148 now $99</a></strong><br />Athleisure apparel isn’t just for cozy, low-intensity workouts. Soft clothes like this jersey half-zip are an essential addition to your wardrobe for lazing around on off days. This half-zip’s textured, cotton-blend fabric is stretchy and breathable on the outside, and it’s equipped with a soft brushed interior for boosted comfort.<a class="view-deal button" href="https://shop.lululemon.com/p/ease-the-day-half-zip/h0x4mw5adm?color=80675" target="_blank" rel="nofollow" data-dimension112="4b47b3b8-cbce-11f1-ba0e-a77537f93232" data-action="Deal Block" data-label="Ease The Day Half Zip (Men's)" data-dimension48="Ease The Day Half Zip (Men's)" data-dimension25="$99">View Deal</a></p></div><h3 class="article-body__section" id="section-shop-more-deals"><span>Shop more deals</span></h3><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Everything&amp;rows=6&amp;view_mode=savings_squad&amp;widget_title=Top+Deals+Handpicked+by+Our+Editors&amp;widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&amp;bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const finalHref = cardLink.href || cardLink.getAttribute('href') || '';                let actualRevenueId = cardLink.getAttribute('data-revenue-id');                const revMatch = finalHref.match(/(?:subId1|xcust|clickref|ascsubtag)=[^&]*?(\d{18,20})(?:&|$)/i);                if (revMatch && revMatch[1]) {                  actualRevenueId = revMatch[1];                }                const rewrittenLink = finalHref;                const revenueId = actualRevenueId;                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = this.decodeHTML(description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim());                summaryTitle = this.decodeHTML(summaryTitle);                                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.getFilteredDeals().slice(0, this.displayLimit), this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.getFilteredDeals().slice(0, this.displayLimit), this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.getFilteredDeals().slice(0, this.displayLimit), 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: this.decodeHTML(item.name || item.title || item.model_name || item.product_name || 'Unknown Product'),            brand: this.decodeHTML(item.brand || ''),            productName: this.decodeHTML(item.model_name || item.product_name || item.name || ''),            merchant: this.decodeHTML(item.merchant_name || item.merchant || item.retailer || 'Retailer'),            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const finalHref = btn.href || btn.getAttribute('href') || '';                let actualRevenueId = btn.getAttribute('data-revenue-id');                const revMatch = finalHref.match(/(?:subId1|xcust|clickref|ascsubtag)=[^&]*?(\d{18,20})(?:&|$)/i);                if (revMatch && revMatch[1]) {                  actualRevenueId = revMatch[1];                }                const rewrittenLink = finalHref;                const revenueId = actualRevenueId;                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 40px; min-height: 40px;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 36px; min-height: 36px;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness/lululemon-just-restocked-its-we-made-too-much-section-here-are-9-fall-finds-under-usd100</link>
                                                                            <description>
                            <![CDATA[ Lululemon's We Made Too Much section just restocked! I've rounded up my absolute favorite styles for fall and they're all under $100. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">3SmhGScBNpEFdBHLXoabQF</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/nYj6YeE5dG9Vbwtc66NUKY-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 19 Oct 2026 15:30:25 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Fitness]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Olivia Halevy ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/YAg7Fmh9dGKbg3hULBMWiU-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Olivia is a Deals Writer at Tom’s Guide. She loves all things lifestyle, shopping and sourcing the best deals from some of the top brands, retailers and websites around. From fashion and beauty to smart home and tech, she has an eye for finding practical, stylish, and reasonably-priced items that help make life simpler (and a little more aesthetically-pleasing).&amp;nbsp;Olivia has over five years of experience writing lifestyle, commerce, and branded content for &lt;a href=&quot;http://patch.com/&quot;&gt;Patch.com&lt;/a&gt;. She&#039;s covered major shopping holidays like Amazon Prime Day, Black Friday and Cyber Monday. In her free time, she enjoys trying out new exercise classes, binge-watching the latest viral TV shows, cooking, spending time with family and taking long walks with her dog, Gus.&amp;nbsp;&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/nYj6YeE5dG9Vbwtc66NUKY-1920-80.jpg">
                                                            <media:credit><![CDATA[Lululemon]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Lululemon deals]]></media:description>                                                            <media:text><![CDATA[Lululemon deals]]></media:text>
                                <media:title type="plain"><![CDATA[Lululemon deals]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/nYj6YeE5dG9Vbwtc66NUKY-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Ready to refresh your fitness wardrobe for fall? Lululemon has you covered, whether you’re looking for new gym essentials or a cozy sweatshirt to keep you warm as the temperatures drop.</p><p>In fact, <a href="https://shop.lululemon.com/c/we-made-too-much/n18mhd" target="_blank" rel="nofollow">the brand recently restocked its 'We Made Too Much' section</a>. I did some digging and found a ton of great styles that are under $100. If you're looking to stock up on affordable fitness pieces, keep scrolling to check out my favorite picks for fall. </p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><a href="https://shop.lululemon.com/c/we-made-too-much/n18mhd" target="_blank" rel="nofollow"><strong>shop Lululemon's 'We Made Too Much' section</strong></a></li><li><strong>Align Tank Top (Women's): </strong><a href="https://shop.lululemon.com/p/align-tank/mnt6w420dl?color=77007" target="_blank" rel="nofollow"><strong>was $68 now $49</strong></a></li><li><strong>Swiftly Tech Long-Sleeve Shirt 2.0: </strong><a href="https://shop.lululemon.com/p/swiftly-tech-ls-2-race/o7l7jc0lss?color=79549" target="_blank" rel="nofollow"><strong>was $78 now $54</strong></a></li><li><strong>Align High-Rise Pant 28": </strong><a href="https://shop.lululemon.com/p/align-pant-full-length-28/vggwe5mu1w?color=77007" target="_blank" rel="nofollow"><strong>was $98 now $69</strong></a></li><li><strong>BeCalm Mid-Rise Wide-Leg Pant: </strong><a href="https://shop.lululemon.com/p/becalm-mid-rise-wide-leg-pant/fx7b5sldlb?color=33454" target="_blank" rel="nofollow"><strong>was $98 now $59</strong></a></li><li><strong>Define Cropped Nulu Jacket: </strong><a href="https://shop.lululemon.com/p/nulu-cropped-define-jacket/oo2vz3qc01?color=77066&amp;sz=4" target="_blank" rel="nofollow"><strong>was $128 now $99</strong></a></li></ul><h3 class="article-body__section" id="section-lululemon-deals"><span>Lululemon Deals</span></h3><div class="product"><a data-dimension112="4b47b0a2-cbce-11f1-9267-3393ab76c93e" data-action="Deal Block" data-label="Dual Pouch Wristlet" data-dimension48="Dual Pouch Wristlet" data-dimension25="$39" href="https://shop.lululemon.com/p/dual-pouch-wristlet/cicnujjsok?color=76797" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1440px;"><p class="vanilla-image-block" style="padding-top:120.00%;"><img id="jYPKTpKt3PdciCh2M8kquJ" name="Wristlet" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jYPKTpKt3PdciCh2M8kquJ-1920-80.jpg" mos="" align="middle" fullscreen="" width="1440" height="1728" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/dual-pouch-wristlet/cicnujjsok?color=76797" target="_blank" rel="nofollow" data-dimension112="4b47b0a2-cbce-11f1-9267-3393ab76c93e" data-action="Deal Block" data-label="Dual Pouch Wristlet" data-dimension48="Dual Pouch Wristlet" data-dimension25="$39">Dual Pouch Wristlet: was $48 now $39</a></strong><br />This cute wristlet keeps all your small items in place while you're on the move. It comes with two zippered pouches and will have you ready to go in the flick of a wrist. <a class="view-deal button" href="https://shop.lululemon.com/p/dual-pouch-wristlet/cicnujjsok?color=76797" target="_blank" rel="nofollow" data-dimension112="4b47b0a2-cbce-11f1-9267-3393ab76c93e" data-action="Deal Block" data-label="Dual Pouch Wristlet" data-dimension48="Dual Pouch Wristlet" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="4b47b16a-cbce-11f1-9c69-3f3e23e4cb22" data-action="Deal Block" data-label="Mesh Soft Jersey Short-Sleeve Shirt (Men's)" data-dimension48="Mesh Soft Jersey Short-Sleeve Shirt (Men's)" data-dimension25="$44" href="https://shop.lululemon.com/p/mesh-soft-jersey-short-sleeve-shirt/b3nwac6tbb?color=0001" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:120.00%;"><img id="sNvV6WjjMp69XVcKVzp7DM" name="long sleeve shirt" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/sNvV6WjjMp69XVcKVzp7DM-1920-80.jpg" mos="" align="middle" fullscreen="" width="1800" height="2160" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/mesh-soft-jersey-short-sleeve-shirt/b3nwac6tbb?color=0001" target="_blank" rel="nofollow" data-dimension112="4b47b16a-cbce-11f1-9c69-3f3e23e4cb22" data-action="Deal Block" data-label="Mesh Soft Jersey Short-Sleeve Shirt (Men's)" data-dimension48="Mesh Soft Jersey Short-Sleeve Shirt (Men's)" data-dimension25="$44">Mesh Soft Jersey Short-Sleeve Shirt (Men's): was $58 now $44</a></strong><br />This is the ultimate training tee you've been looking for. It's made with a lightweight material that feels cozy against the skin, yet looks stylish enough to wear for a night out. As a bonus, this shirt's fabric features quick-drying and sweat-wicking material. <a class="view-deal button" href="https://shop.lululemon.com/p/mesh-soft-jersey-short-sleeve-shirt/b3nwac6tbb?color=0001" target="_blank" rel="nofollow" data-dimension112="4b47b16a-cbce-11f1-9c69-3f3e23e4cb22" data-action="Deal Block" data-label="Mesh Soft Jersey Short-Sleeve Shirt (Men's)" data-dimension48="Mesh Soft Jersey Short-Sleeve Shirt (Men's)" data-dimension25="$44">View Deal</a></p></div><div class="product"><a data-dimension112="4b47b106-cbce-11f1-b97e-affda28134f6" data-action="Deal Block" data-label="Align Tank Top (Women's)" data-dimension48="Align Tank Top (Women's)" data-dimension25="$49" href="https://shop.lululemon.com/p/align-tank/mnt6w420dl?color=77007" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:120.00%;"><img id="bKRE3xAww39376wSTqb4ah" name="lululemon Align" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bKRE3xAww39376wSTqb4ah-1920-80.jpg" mos="" align="middle" fullscreen="" width="1800" height="2160" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/align-tank/mnt6w420dl?color=77007" target="_blank" rel="nofollow" data-dimension112="4b47b106-cbce-11f1-b97e-affda28134f6" data-action="Deal Block" data-label="Align Tank Top (Women's)" data-dimension48="Align Tank Top (Women's)" data-dimension25="$49">Align Tank Top (Women's): was $68 now $49</a></strong><br />This super-soft, super-comfortable tank top has a built-in bra for light support during hikes, Pilates, and yoga classes. It’s soft and sweat-wicking and comes in several different colorways to suit every style. It’s also slightly cropped to allow you to move through different yoga poses. <a class="view-deal button" href="https://shop.lululemon.com/p/align-tank/mnt6w420dl?color=77007" target="_blank" rel="nofollow" data-dimension112="4b47b106-cbce-11f1-b97e-affda28134f6" data-action="Deal Block" data-label="Align Tank Top (Women's)" data-dimension48="Align Tank Top (Women's)" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="4b47b1ce-cbce-11f1-86e6-9d37f07a968f" data-action="Deal Block" data-label="Swiftly Tech Long-Sleeve Shirt 2.0 Waist Length (Women's)" data-dimension48="Swiftly Tech Long-Sleeve Shirt 2.0 Waist Length (Women's)" data-dimension25="$54" href="https://shop.lululemon.com/p/tops-long-sleeve/Swiftly-Tech-LS-2-Race-MD/_/prod9820340?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:120.00%;"><img id="XoSWXGqQwcoKgthBaaupyn" name="long sleeve" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XoSWXGqQwcoKgthBaaupyn-1920-80.jpg" mos="" align="middle" fullscreen="" width="1800" height="2160" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/tops-long-sleeve/Swiftly-Tech-LS-2-Race-MD/_/prod9820340?" target="_blank" rel="nofollow" data-dimension112="4b47b1ce-cbce-11f1-86e6-9d37f07a968f" data-action="Deal Block" data-label="Swiftly Tech Long-Sleeve Shirt 2.0 Waist Length (Women's)" data-dimension48="Swiftly Tech Long-Sleeve Shirt 2.0 Waist Length (Women's)" data-dimension25="$54">Swiftly Tech Long-Sleeve Shirt 2.0 Waist Length (Women's): was $78 now $54</a></strong><br />This is the perfect layer to have in your wardrobe. The swiftly tech tops have been a Lululemon staple for decades, and you can wear (and wash) them again and again without them going smelly or shrinking. <a class="view-deal button" href="https://shop.lululemon.com/p/tops-long-sleeve/Swiftly-Tech-LS-2-Race-MD/_/prod9820340?" target="_blank" rel="nofollow" data-dimension112="4b47b1ce-cbce-11f1-86e6-9d37f07a968f" data-action="Deal Block" data-label="Swiftly Tech Long-Sleeve Shirt 2.0 Waist Length (Women's)" data-dimension48="Swiftly Tech Long-Sleeve Shirt 2.0 Waist Length (Women's)" data-dimension25="$54">View Deal</a></p></div><div class="product"><a data-dimension112="4b47b296-cbce-11f1-aa82-f7ef03357455" data-action="Deal Block" data-label="BeCalm Mid-Rise Wide-Leg Pant (Women's)" data-dimension48="BeCalm Mid-Rise Wide-Leg Pant (Women's)" data-dimension25="$59" href="https://shop.lululemon.com/p/becalm-mid-rise-wide-leg-pant/fx7b5sldlb?color=33454" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1440px;"><p class="vanilla-image-block" style="padding-top:120.00%;"><img id="ZpgP85PS6xp6USEEmqD8om" name="lululemon pant" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZpgP85PS6xp6USEEmqD8om-1920-80.jpg" mos="" align="middle" fullscreen="" width="1440" height="1728" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/becalm-mid-rise-wide-leg-pant/fx7b5sldlb?color=33454" target="_blank" rel="nofollow" data-dimension112="4b47b296-cbce-11f1-aa82-f7ef03357455" data-action="Deal Block" data-label="BeCalm Mid-Rise Wide-Leg Pant (Women's)" data-dimension48="BeCalm Mid-Rise Wide-Leg Pant (Women's)" data-dimension25="$59">BeCalm Mid-Rise Wide-Leg Pant (Women's): was $98 now $59</a></strong><br />These pants are luxuriously comfortable, making them great for couch surfing, but have a chic and smart look that works on days out too. They're made with French terry and are soft to the touch. I need pants that do both, so I feel like these are a smart choice.<a class="view-deal button" href="https://shop.lululemon.com/p/becalm-mid-rise-wide-leg-pant/fx7b5sldlb?color=33454" target="_blank" rel="nofollow" data-dimension112="4b47b296-cbce-11f1-aa82-f7ef03357455" data-action="Deal Block" data-label="BeCalm Mid-Rise Wide-Leg Pant (Women's)" data-dimension48="BeCalm Mid-Rise Wide-Leg Pant (Women's)" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="4b47b228-cbce-11f1-b72a-b5f887c49ee4" data-action="Deal Block" data-label="Align High-Rise Pant 28" (Women's)" data-dimension48="Align High-Rise Pant 28" (Women's)" data-dimension25="$69" href="https://shop.lululemon.com/p/align-pant-full-length-28/vggwe5mu1w?color=77007" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:120.00%;"><img id="MiCGD28QzTaN9eQYAiWe3Q" name="lululemon high rise" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/MiCGD28QzTaN9eQYAiWe3Q-1920-80.jpg" mos="" align="middle" fullscreen="" width="1800" height="2160" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/align-pant-full-length-28/vggwe5mu1w?color=77007" target="_blank" rel="nofollow" data-dimension112="4b47b228-cbce-11f1-b72a-b5f887c49ee4" data-action="Deal Block" data-label="Align High-Rise Pant 28" (Women's)" data-dimension48="Align High-Rise Pant 28" (Women's)" data-dimension25="$69">Align High-Rise Pant 28" (Women's): was $98 now $69</a></strong><br />On sale from $69, the popular Align leggings are a great buy. We love these due to their comfortable, sculpted fit,  and extremely soft fabric. They also stretch with you and wick sweat while you're working out.<a class="view-deal button" href="https://shop.lululemon.com/p/align-pant-full-length-28/vggwe5mu1w?color=77007" target="_blank" rel="nofollow" data-dimension112="4b47b228-cbce-11f1-b72a-b5f887c49ee4" data-action="Deal Block" data-label="Align High-Rise Pant 28" (Women's)" data-dimension48="Align High-Rise Pant 28" (Women's)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="4b47b2f0-cbce-11f1-aeb6-27d3b3cb8e54" data-action="Deal Block" data-label="Scuba Evolve Oversized Half-Zip Hoodie (Women's)" data-dimension48="Scuba Evolve Oversized Half-Zip Hoodie (Women's)" data-dimension25="$94" href="https://shop.lululemon.com/p/scuba-evolve-oversized-half-zip-hoodie/lp4yqrz3sp?color=76925" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:119.94%;"><img id="i5m2KDsgHt4RywbcyUmMRk" name="scuba evolve" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/i5m2KDsgHt4RywbcyUmMRk-1920-80.jpg" mos="" align="middle" fullscreen="" width="1800" height="2159" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/scuba-evolve-oversized-half-zip-hoodie/lp4yqrz3sp?color=76925" target="_blank" rel="nofollow" data-dimension112="4b47b2f0-cbce-11f1-aeb6-27d3b3cb8e54" data-action="Deal Block" data-label="Scuba Evolve Oversized Half-Zip Hoodie (Women's)" data-dimension48="Scuba Evolve Oversized Half-Zip Hoodie (Women's)" data-dimension25="$94">Scuba Evolve Oversized Half-Zip Hoodie (Women's): was $128 now $94</a></strong><br />This half-zip scuba hoodie exudes comfortability. It's made with a plush, cotton-blend fleece fabric that's naturally breathable and insanely soft against the skin. Then, the oversized fit is perfect for throwing over a sports bra on your way to the gym or for reaching maximum coziness at home.<a class="view-deal button" href="https://shop.lululemon.com/p/scuba-evolve-oversized-half-zip-hoodie/lp4yqrz3sp?color=76925" target="_blank" rel="nofollow" data-dimension112="4b47b2f0-cbce-11f1-aeb6-27d3b3cb8e54" data-action="Deal Block" data-label="Scuba Evolve Oversized Half-Zip Hoodie (Women's)" data-dimension48="Scuba Evolve Oversized Half-Zip Hoodie (Women's)" data-dimension25="$94">View Deal</a></p></div><div class="product"><a data-dimension112="4b47b354-cbce-11f1-95cb-a9406c5ab5f1" data-action="Deal Block" data-label="Define Cropped Nulu Jacket (Women's)" data-dimension48="Define Cropped Nulu Jacket (Women's)" data-dimension25="$99" href="https://shop.lululemon.com/p/nulu-cropped-define-jacket/oo2vz3qc01?color=77584" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:120.00%;"><img id="4DSvzmsKSiPsZWmTobcmz5" name="nulu jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4DSvzmsKSiPsZWmTobcmz5-1920-80.jpg" mos="" align="middle" fullscreen="" width="1800" height="2160" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/nulu-cropped-define-jacket/oo2vz3qc01?color=77584" target="_blank" rel="nofollow" data-dimension112="4b47b354-cbce-11f1-95cb-a9406c5ab5f1" data-action="Deal Block" data-label="Define Cropped Nulu Jacket (Women's)" data-dimension48="Define Cropped Nulu Jacket (Women's)" data-dimension25="$99">Define Cropped Nulu Jacket (Women's): was $128 now $99</a></strong><br />Made from Lululemon’s famously buttery-soft Nulu fabric, this lightweight jacket is perfect for throwing on over workout gear. It pairs nicely with high-rise leggings, biker shorts or trousers and comes with zippered pockets and thumbholes to stop sleeves riding up mid-workout.<a class="view-deal button" href="https://shop.lululemon.com/p/nulu-cropped-define-jacket/oo2vz3qc01?color=77584" target="_blank" rel="nofollow" data-dimension112="4b47b354-cbce-11f1-95cb-a9406c5ab5f1" data-action="Deal Block" data-label="Define Cropped Nulu Jacket (Women's)" data-dimension48="Define Cropped Nulu Jacket (Women's)" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="4b47b3b8-cbce-11f1-ba0e-a77537f93232" data-action="Deal Block" data-label="Ease The Day Half Zip (Men's)" data-dimension48="Ease The Day Half Zip (Men's)" data-dimension25="$99" href="https://shop.lululemon.com/p/ease-the-day-half-zip/h0x4mw5adm?color=80675" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:120.00%;"><img id="ZjAAUq5gXJx9ert8yRZG6Z" name="half zip" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZjAAUq5gXJx9ert8yRZG6Z-1920-80.jpg" mos="" align="middle" fullscreen="" width="1800" height="2160" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://shop.lululemon.com/p/ease-the-day-half-zip/h0x4mw5adm?color=80675" target="_blank" rel="nofollow" data-dimension112="4b47b3b8-cbce-11f1-ba0e-a77537f93232" data-action="Deal Block" data-label="Ease The Day Half Zip (Men's)" data-dimension48="Ease The Day Half Zip (Men's)" data-dimension25="$99">Ease The Day Half Zip (Men's): was $148 now $99</a></strong><br />Athleisure apparel isn’t just for cozy, low-intensity workouts. Soft clothes like this jersey half-zip are an essential addition to your wardrobe for lazing around on off days. This half-zip’s textured, cotton-blend fabric is stretchy and breathable on the outside, and it’s equipped with a soft brushed interior for boosted comfort.<a class="view-deal button" href="https://shop.lululemon.com/p/ease-the-day-half-zip/h0x4mw5adm?color=80675" target="_blank" rel="nofollow" data-dimension112="4b47b3b8-cbce-11f1-ba0e-a77537f93232" data-action="Deal Block" data-label="Ease The Day Half Zip (Men's)" data-dimension48="Ease The Day Half Zip (Men's)" data-dimension25="$99">View Deal</a></p></div><h3 class="article-body__section" id="section-shop-more-deals"><span>Shop more deals</span></h3><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Everything&amp;rows=6&amp;view_mode=savings_squad&amp;widget_title=Top+Deals+Handpicked+by+Our+Editors&amp;widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&amp;bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const finalHref = cardLink.href || cardLink.getAttribute('href') || '';                let actualRevenueId = cardLink.getAttribute('data-revenue-id');                const revMatch = finalHref.match(/(?:subId1|xcust|clickref|ascsubtag)=[^&]*?(\d{18,20})(?:&|$)/i);                if (revMatch && revMatch[1]) {                  actualRevenueId = revMatch[1];                }                const rewrittenLink = finalHref;                const revenueId = actualRevenueId;                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = this.decodeHTML(description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim());                summaryTitle = this.decodeHTML(summaryTitle);                                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.getFilteredDeals().slice(0, this.displayLimit), this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.getFilteredDeals().slice(0, this.displayLimit), this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.getFilteredDeals().slice(0, this.displayLimit), 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: this.decodeHTML(item.name || item.title || item.model_name || item.product_name || 'Unknown Product'),            brand: this.decodeHTML(item.brand || ''),            productName: this.decodeHTML(item.model_name || item.product_name || item.name || ''),            merchant: this.decodeHTML(item.merchant_name || item.merchant || item.retailer || 'Retailer'),            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const finalHref = btn.href || btn.getAttribute('href') || '';                let actualRevenueId = btn.getAttribute('data-revenue-id');                const revMatch = finalHref.match(/(?:subId1|xcust|clickref|ascsubtag)=[^&]*?(\d{18,20})(?:&|$)/i);                if (revMatch && revMatch[1]) {                  actualRevenueId = revMatch[1];                }                const rewrittenLink = finalHref;                const revenueId = actualRevenueId;                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 40px; min-height: 40px;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 36px; min-height: 36px;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 27 fall walking shoe deals: Biggest savings with up to 61% off Skechers, Birkenstocks and New Balance ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Enjoying the fall weather? To make your walks even more enjoyable, you can save a bunch on best selling walking shoes right now. There are discounts to be found on everything from Skechers slip-ins to comfortable Birkenstock sandals.</p><p>Right now <a href="https://www.amazon.com/b?node=211953829011&amp;ref_=shoes&amp;pf_rd_p=b017f2eb-1ce1-408d-8152-3fb62c1c7cbe&amp;pf_rd_r=T1P1PSA2E0E72KS74A8H" target="_blank" rel="nofollow">Amazon is offering deals on boots, mules, cozy slippers and more</a>. I'm also a fan of <a href="https://www.asics.com/us/en-us/sportstyle-clearance/c/aa11015000/" target="_blank" rel="nofollow">Asics current sale</a> as there are plenty of Sportstyle sneakers available at a lower price than usual.</p><p><strong>Note: </strong>prices can vary depending on the size and color you select. To find the best deals, check out the different colors available in your size.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links </span></h3><ul><li><strong>Asics: </strong><a href="https://www.asics.com/us/en-us/clearance/c/aa60000000/?" target="_blank" rel="nofollow"><strong>deals from $49</strong></a></li><li><strong>Brooks: </strong><a href="https://www.amazon.com/stores/Brooks/page/B6834DFA-396F-4E38-98F6-3D2739393271?" target="_blank" rel="nofollow"><strong>up to 40% off</strong></a></li><li><strong>Hoka: </strong><a href="https://www.hoka.com/en/us/sale/" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li><li><strong>Nike: </strong><a href="https://www.nike.com/w/mens-shoes-nik1zy7ok" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li><li><strong>New Balance: </strong><a href="https://www.amazon.com/stores/NewBalanceAthleticShoeInc/page/855D4CDF-ADB7-4BE8-9E26-A085D029E4B5" target="_blank" rel="nofollow"><strong>deals from $39</strong></a></li><li><strong>Skechers: </strong><a href="https://www.skechers.com/women/shop-by-activity/walking/" target="_blank" rel="nofollow"><strong>20% off for members</strong></a></li></ul><h3 class="article-body__section" id="section-skechers"><span>Skechers</span></h3><div class="product"><a data-dimension112="5a29d47e-cba6-11f1-aad6-a7ffa4f1850d" data-action="Deal Block" data-label="Refine 2.0 Nora (Women's)" data-dimension48="Refine 2.0 Nora (Women's)" data-dimension25="$32" href="https://www.amazon.com/Skechers-Womens-Sport-Active-Refine/dp/B0G1PK31X7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:66.91%;"><img id="XtYccaXnTY5XF946soUYSE" name="Refine 2.0 Nora (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XtYccaXnTY5XF946soUYSE-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="465" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Sport-Active-Refine/dp/B0G1PK31X7" target="_blank" rel="nofollow" data-dimension112="5a29d47e-cba6-11f1-aad6-a7ffa4f1850d" data-action="Deal Block" data-label="Refine 2.0 Nora (Women's)" data-dimension48="Refine 2.0 Nora (Women's)" data-dimension25="$32">Refine 2.0 Nora (Women's): was $84 now $32</a></strong><br />These Skechers have seen an impressive $52 discount. Incredibly easy to wear, they feature a stretch knit upper, arch-fit insoles and are machine washable. The neutral design makes them easy to style, too.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Sport-Active-Refine/dp/B0G1PK31X7" target="_blank" rel="nofollow" data-dimension112="5a29d47e-cba6-11f1-aad6-a7ffa4f1850d" data-action="Deal Block" data-label="Refine 2.0 Nora (Women's)" data-dimension48="Refine 2.0 Nora (Women's)" data-dimension25="$32">View Deal</a></p></div><div class="product"><a data-dimension112="b35519ba-cd30-11f1-be57-83d526322683" data-action="Deal Block" data-label="Flex Appeal 4.0-Livin' in This Sport Sandal (Women's)" data-dimension48="Flex Appeal 4.0-Livin' in This Sport Sandal (Women's)" data-dimension25="$41" href="https://www.amazon.com/Skechers-Womens-Appeal-4-0-Livin-Sandal/dp/B0CDKP7SL6" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:63.88%;"><img id="hvAgkNmHzWtvwtfLxAYGpQ" name="Flex Appeal 4.0-Livin' in This Sport Sandal (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hvAgkNmHzWtvwtfLxAYGpQ-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="444" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Appeal-4-0-Livin-Sandal/dp/B0CDKP7SL6" target="_blank" rel="nofollow" data-dimension112="b35519ba-cd30-11f1-be57-83d526322683" data-action="Deal Block" data-label="Flex Appeal 4.0-Livin' in This Sport Sandal (Women's)" data-dimension48="Flex Appeal 4.0-Livin' in This Sport Sandal (Women's)" data-dimension25="$41">Flex Appeal 4.0-Livin' in This Sport Sandal (Women's): was $49 now $41</a></strong><br />These Skechers sandals have seen significant discounts in certain sizes and colors, so grab a pair and put them away for next summer! These have a super soft Yoga Foam sole and unlike most sandals, stay securely on your feet thanks to their stretchy knit upper.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Appeal-4-0-Livin-Sandal/dp/B0CDKP7SL6" target="_blank" rel="nofollow" data-dimension112="b35519ba-cd30-11f1-be57-83d526322683" data-action="Deal Block" data-label="Flex Appeal 4.0-Livin' in This Sport Sandal (Women's)" data-dimension48="Flex Appeal 4.0-Livin' in This Sport Sandal (Women's)" data-dimension25="$41">View Deal</a></p></div><div class="product"><a data-dimension112="b57f113a-cc6a-11f1-a899-c1f010793431" data-action="Deal Block" data-label="Flex Adapt Juliette (Women's)" data-dimension48="Flex Adapt Juliette (Women's)" data-dimension25="$42" href="https://www.amazon.com/Skechers-Womens-Slip-Loafer-Black/dp/B0FG9VLFZM" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:64.89%;"><img id="j8oCtLFQLWPvQmWbeNMJU9" name="Flex Adapt Juliette (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/j8oCtLFQLWPvQmWbeNMJU9-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="451" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Slip-Loafer-Black/dp/B0FG9VLFZM" target="_blank" rel="nofollow" data-dimension112="b57f113a-cc6a-11f1-a899-c1f010793431" data-action="Deal Block" data-label="Flex Adapt Juliette (Women's)" data-dimension48="Flex Adapt Juliette (Women's)" data-dimension25="$42">Flex Adapt Juliette (Women's): was $79 now $42</a></strong><br />This discount is available in limited sizes and colors, so make sure to grab it if it's available in your size. The Skechers Flex Adapt Juliette have a super-simple and sweet look that's very easy to style, and even easier to wear. The stretch knit upper feels just like a comfy pair of socks.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Slip-Loafer-Black/dp/B0FG9VLFZM" target="_blank" rel="nofollow" data-dimension112="b57f113a-cc6a-11f1-a899-c1f010793431" data-action="Deal Block" data-label="Flex Adapt Juliette (Women's)" data-dimension48="Flex Adapt Juliette (Women's)" data-dimension25="$42">View Deal</a></p></div><div class="product"><a data-dimension112="5a29d4ec-cba6-11f1-b115-d7a225eed3a8" data-action="Deal Block" data-label="Sloan Slip-In Sneakers (Men's)" data-dimension48="Sloan Slip-In Sneakers (Men's)" data-dimension25="$43" href="https://www.amazon.com/Skechers-Knitted-Bungee-Slip-Sneakers/dp/B0FNLWG66B/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:69.21%;"><img id="nYRVX4hTE2gNxHqkbBmWTG" name="Sloan Slip-In Sneakers (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/nYRVX4hTE2gNxHqkbBmWTG-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="481" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Knitted-Bungee-Slip-Sneakers/dp/B0FNLWG66B/" target="_blank" rel="nofollow" data-dimension112="5a29d4ec-cba6-11f1-b115-d7a225eed3a8" data-action="Deal Block" data-label="Sloan Slip-In Sneakers (Men's)" data-dimension48="Sloan Slip-In Sneakers (Men's)" data-dimension25="$43">Sloan Slip-In Sneakers (Men's): was $85 now $43</a></strong><br />You can save 49% on the Skechers Sloan for a limited time, so if it's in stock in your size, don't miss it! The brown-and-orange colorway is super stylish, and you get a visible air cushion unit at the side.<a class="view-deal button" href="https://www.amazon.com/Skechers-Knitted-Bungee-Slip-Sneakers/dp/B0FNLWG66B/" target="_blank" rel="nofollow" data-dimension112="5a29d4ec-cba6-11f1-b115-d7a225eed3a8" data-action="Deal Block" data-label="Sloan Slip-In Sneakers (Men's)" data-dimension48="Sloan Slip-In Sneakers (Men's)" data-dimension25="$43">View Deal</a></p></div><div class="product"><a data-dimension112="5a29d550-cba6-11f1-b886-4f7ac3077f2e" data-action="Deal Block" data-label="Wilshire Blvd Knit Sail (Women's)" data-dimension48="Wilshire Blvd Knit Sail (Women's)" data-dimension25="$45" href="https://www.amazon.com/Skechers-Womens-Slip-Boat-White/dp/B0D9PMGCTG" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1006px;"><p class="vanilla-image-block" style="padding-top:69.09%;"><img id="K2ZyHfXK9RpXVL5s5syuw6" name="Wilshire Blvd Knit Sail (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/K2ZyHfXK9RpXVL5s5syuw6-1920-80.jpg" mos="" align="middle" fullscreen="" width="1006" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Slip-Boat-White/dp/B0D9PMGCTG" target="_blank" rel="nofollow" data-dimension112="5a29d550-cba6-11f1-b886-4f7ac3077f2e" data-action="Deal Block" data-label="Wilshire Blvd Knit Sail (Women's)" data-dimension48="Wilshire Blvd Knit Sail (Women's)" data-dimension25="$45">Wilshire Blvd Knit Sail (Women's): was $70 now $45</a></strong><br />These knitted Skechers give off the perfect cozy vibe for fall. They don't even feel like wearing shoes — Skechers says they provide socklike comfort. I especially adore the bow detail on the toe. <a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Slip-Boat-White/dp/B0D9PMGCTG" target="_blank" rel="nofollow" data-dimension112="5a29d550-cba6-11f1-b886-4f7ac3077f2e" data-action="Deal Block" data-label="Wilshire Blvd Knit Sail (Women's)" data-dimension48="Wilshire Blvd Knit Sail (Women's)" data-dimension25="$45">View Deal</a></p></div><div class="product"><a data-dimension112="b3551a5a-cd30-11f1-91b4-a3ae6bc157d3" data-action="Deal Block" data-label="Cleo Bewitch Ballet Flat (Women's)" data-dimension48="Cleo Bewitch Ballet Flat (Women's)" data-dimension25="$46" href="https://www.amazon.com/Skechers-Womens-Bewitch-Ballet-Black/dp/B08L5J6N5X" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:872px;"><p class="vanilla-image-block" style="padding-top:33.26%;"><img id="4zHiCZtnHGSthG3GrZpZw4" name="516NWIhEd8L._AC_SY695_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4zHiCZtnHGSthG3GrZpZw4-1920-80.jpg" mos="" align="middle" fullscreen="" width="872" height="290" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Bewitch-Ballet-Black/dp/B08L5J6N5X" target="_blank" rel="nofollow" data-dimension112="b3551a5a-cd30-11f1-91b4-a3ae6bc157d3" data-action="Deal Block" data-label="Cleo Bewitch Ballet Flat (Women's)" data-dimension48="Cleo Bewitch Ballet Flat (Women's)" data-dimension25="$46">Cleo Bewitch Ballet Flat (Women's): was $49 now $46</a></strong><br />For a sleek, comfortable pair of shoes, try these Skechers Cleo Bewitch Ballet Flats. They feature Skechers Air Cooled Memory Foam soles, and breathable stretch knit uppers. Reviewers on Amazon say these shoes go with everything and can be worn all day.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Bewitch-Ballet-Black/dp/B08L5J6N5X" target="_blank" rel="nofollow" data-dimension112="b3551a5a-cd30-11f1-91b4-a3ae6bc157d3" data-action="Deal Block" data-label="Cleo Bewitch Ballet Flat (Women's)" data-dimension48="Cleo Bewitch Ballet Flat (Women's)" data-dimension25="$46">View Deal</a></p></div><div class="product"><a data-dimension112="5a29d5be-cba6-11f1-bd2f-798e978702b7" data-action="Deal Block" data-label="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension48="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension25="$57" href="https://www.amazon.com/Skechers-Mens-Walk-Flex-Hands-Sneaker/dp/B0CFN8VR99" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:54.68%;"><img id="DsBvJExJKzNCdDFDnDXn3T" name="71y3Wpz-YFL._AC_SX695_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/DsBvJExJKzNCdDFDnDXn3T-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="380" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Mens-Walk-Flex-Hands-Sneaker/dp/B0CFN8VR99" target="_blank" rel="nofollow" data-dimension112="5a29d5be-cba6-11f1-bd2f-798e978702b7" data-action="Deal Block" data-label="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension48="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension25="$57">Slip-Ins Go Walk Flex Hands Up Sneaker: was $84 now $57</a></strong><br />A comfortable, reliable shoe, the Skechers Go Walk Flex Hands Up are now on sale starting from just $57. These come in a range of muted shades, meaning they're easy to pair with a range of outfits, and have Ultra Go cushioning to keep you light on your feet. Make sure to add a pair to your basket! <a class="view-deal button" href="https://www.amazon.com/Skechers-Mens-Walk-Flex-Hands-Sneaker/dp/B0CFN8VR99" target="_blank" rel="nofollow" data-dimension112="5a29d5be-cba6-11f1-bd2f-798e978702b7" data-action="Deal Block" data-label="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension48="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension25="$57">View Deal</a></p></div><h3 class="article-body__section" id="section-birkenstocks"><span>Birkenstocks</span></h3><div class="product"><a data-dimension112="5a29d690-cba6-11f1-849e-47b50a3b8654" data-action="Deal Block" data-label="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension48="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension25="$30" href="https://www.nordstromrack.com/s/birkenstock-arizona-stealth-buckle-eva-slide-sandal-women/7945865?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1560px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="3Qt2UrH7ESWm55JQpi8aXQ" name="Arizona Stealth" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3Qt2UrH7ESWm55JQpi8aXQ-1920-80.jpg" mos="" align="middle" fullscreen="" width="1560" height="2340" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nordstromrack.com/s/birkenstock-arizona-stealth-buckle-eva-slide-sandal-women/7945865?" target="_blank" rel="nofollow" data-dimension112="5a29d690-cba6-11f1-849e-47b50a3b8654" data-action="Deal Block" data-label="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension48="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension25="$30">Arizona Stealth Buckle EVA Slide (Women's): was $54 now $30</a></strong><br />A pair of Birkenstocks for $30??? Sign me up. Fall might be here, but warm weather is still hanging around. These waterproof slides are perfect for the beach and pool. They feature a rubber-like texture with sleek adjustable straps and a grippy traction sole. <a class="view-deal button" href="https://www.nordstromrack.com/s/birkenstock-arizona-stealth-buckle-eva-slide-sandal-women/7945865?" target="_blank" rel="nofollow" data-dimension112="5a29d690-cba6-11f1-849e-47b50a3b8654" data-action="Deal Block" data-label="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension48="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension25="$30">View Deal</a></p></div><div class="product"><a data-dimension112="5a29d6f4-cba6-11f1-91b0-a1cf04b003e0" data-action="Deal Block" data-label="Madrid Eva Big Buckle (Women's)" data-dimension48="Madrid Eva Big Buckle (Women's)" data-dimension25="$54" href="https://www.amazon.com/Birkenstock-Womens-Madrid-Buckle-11-11-5/dp/B0FH16M2GN" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:41.58%;"><img id="hnaAiVGGAv8vC6hXNTjrfG" name="Madrid Eva Big Buckle (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hnaAiVGGAv8vC6hXNTjrfG-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="289" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Birkenstock-Womens-Madrid-Buckle-11-11-5/dp/B0FH16M2GN" target="_blank" rel="nofollow" data-dimension112="5a29d6f4-cba6-11f1-91b0-a1cf04b003e0" data-action="Deal Block" data-label="Madrid Eva Big Buckle (Women's)" data-dimension48="Madrid Eva Big Buckle (Women's)" data-dimension25="$54">Madrid Eva Big Buckle (Women's): was $66 now $54</a></strong><br />The classic Birkenstock look, without the leather. These EVA big buckle sandels come in a cool Gray Taupe color and are water-friendly, too.<a class="view-deal button" href="https://www.amazon.com/Birkenstock-Womens-Madrid-Buckle-11-11-5/dp/B0FH16M2GN" target="_blank" rel="nofollow" data-dimension112="5a29d6f4-cba6-11f1-91b0-a1cf04b003e0" data-action="Deal Block" data-label="Madrid Eva Big Buckle (Women's)" data-dimension48="Madrid Eva Big Buckle (Women's)" data-dimension25="$54">View Deal</a></p></div><div class="product"><a data-dimension112="5a29d762-cba6-11f1-85fb-556c01a4ea44" data-action="Deal Block" data-label="Papilio Florida Platform Flex (Women's)" data-dimension48="Papilio Florida Platform Flex (Women's)" data-dimension25="$74" href="https://www.nordstromrack.com/s/florida-flex-platform-slide-sandal-women/7953334?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1560px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="YToScW8bDWGEAAJqToJey" name="florida" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/YToScW8bDWGEAAJqToJey-1920-80.jpg" mos="" align="middle" fullscreen="" width="1560" height="2340" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nordstromrack.com/s/florida-flex-platform-slide-sandal-women/7953334?" target="_blank" rel="nofollow" data-dimension112="5a29d762-cba6-11f1-85fb-556c01a4ea44" data-action="Deal Block" data-label="Papilio Florida Platform Flex (Women's)" data-dimension48="Papilio Florida Platform Flex (Women's)" data-dimension25="$74">Papilio Florida Platform Flex (Women's): was $144 now $74</a></strong><br />These Papilio by Birkenstock sandals feature a platform and three straps for extra support. Reviewers love their iconic design and comfortable, adjustable fit.<a class="view-deal button" href="https://www.nordstromrack.com/s/florida-flex-platform-slide-sandal-women/7953334?" target="_blank" rel="nofollow" data-dimension112="5a29d762-cba6-11f1-85fb-556c01a4ea44" data-action="Deal Block" data-label="Papilio Florida Platform Flex (Women's)" data-dimension48="Papilio Florida Platform Flex (Women's)" data-dimension25="$74">View Deal</a></p></div><div class="product"><a data-dimension112="b57f11e4-cc6a-11f1-873c-53c4512c2a48" data-action="Deal Block" data-label="Mayari - Printed Footbed Sandal (Women's)" data-dimension48="Mayari - Printed Footbed Sandal (Women's)" data-dimension25="$90" href="https://www.amazon.com/Birkenstock-Womens-Mayari-Printed-Footbed-Sandal/dp/B0FH1FHW6F" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:46.47%;"><img id="puE7T2AENpTehS3ncU69oY" name="Mayari - Printed Footbed Sandal (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/puE7T2AENpTehS3ncU69oY-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="323" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Birkenstock-Womens-Mayari-Printed-Footbed-Sandal/dp/B0FH1FHW6F" target="_blank" rel="nofollow" data-dimension112="b57f11e4-cc6a-11f1-873c-53c4512c2a48" data-action="Deal Block" data-label="Mayari - Printed Footbed Sandal (Women's)" data-dimension48="Mayari - Printed Footbed Sandal (Women's)" data-dimension25="$90">Mayari - Printed Footbed Sandal (Women's): was $112 now $90</a></strong><br />As well as a soft Pure Sage strap, these Birkenstock sandals have a beautiful floral design printed on the footbed. The double straps and toe loop keep them securely on your feet.<a class="view-deal button" href="https://www.amazon.com/Birkenstock-Womens-Mayari-Printed-Footbed-Sandal/dp/B0FH1FHW6F" target="_blank" rel="nofollow" data-dimension112="b57f11e4-cc6a-11f1-873c-53c4512c2a48" data-action="Deal Block" data-label="Mayari - Printed Footbed Sandal (Women's)" data-dimension48="Mayari - Printed Footbed Sandal (Women's)" data-dimension25="$90">View Deal</a></p></div><h3 class="article-body__section" id="section-cushionaire"><span>Cushionaire</span></h3><div class="product"><a data-dimension112="4a99259e-cdfb-11f1-9750-511e1be1b23c" data-action="Deal Block" data-label="Java Casual Jelly Flats (Women's)" data-dimension48="Java Casual Jelly Flats (Women's)" data-dimension25="$34" href="https://www.amazon.com/dp/B0H4MLLC32" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:514px;"><p class="vanilla-image-block" style="padding-top:135.21%;"><img id="fA5iQ9SRNPyHw3htEEeMiK" name="Java Casual Jelly Flats (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/fA5iQ9SRNPyHw3htEEeMiK-1920-80.jpg" mos="" align="middle" fullscreen="" width="514" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0H4MLLC32" target="_blank" rel="nofollow" data-dimension112="4a99259e-cdfb-11f1-9750-511e1be1b23c" data-action="Deal Block" data-label="Java Casual Jelly Flats (Women's)" data-dimension48="Java Casual Jelly Flats (Women's)" data-dimension25="$34">Java Casual Jelly Flats (Women's): was $49 now $34</a></strong><br />These jelly flats from Cushionaire are flexible, easy to slip on and stay put thanks to a buckle. They feature a water-friendly construction that wipes clean with ease and also makes them practical pool shoes for vacations, errands and busy days. <a class="view-deal button" href="https://www.amazon.com/dp/B0H4MLLC32" target="_blank" rel="nofollow" data-dimension112="4a99259e-cdfb-11f1-9750-511e1be1b23c" data-action="Deal Block" data-label="Java Casual Jelly Flats (Women's)" data-dimension48="Java Casual Jelly Flats (Women's)" data-dimension25="$34">View Deal</a></p></div><div class="product"><a data-dimension112="4a992634-cdfb-11f1-95b6-d1b60e3eb69b" data-action="Deal Block" data-label="Talisa Espadrilles for Women" data-dimension48="Talisa Espadrilles for Women" data-dimension25="$37" href="https://www.amazon.com/dp/B0GXGRQDNQ?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:581px;"><p class="vanilla-image-block" style="padding-top:119.62%;"><img id="UxL9TT6inJkWtC3et4tVLX" name="Talisa" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/UxL9TT6inJkWtC3et4tVLX-1920-80.jpg" mos="" align="middle" fullscreen="" width="581" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0GXGRQDNQ?" target="_blank" rel="nofollow" data-dimension112="4a992634-cdfb-11f1-95b6-d1b60e3eb69b" data-action="Deal Block" data-label="Talisa Espadrilles for Women" data-dimension48="Talisa Espadrilles for Women" data-dimension25="$37">Talisa Espadrilles for Women: was $64 now $37</a></strong><br />If you're looking for a closed-toe shoe that's a bit elevated, these espadrilles are the way to go. They have crossover elastic straps that hug your ankle for a secure fit and they stretch as you move. They also have a slight wedge that's still comfortable enough to walk on. <a class="view-deal button" href="https://www.amazon.com/dp/B0GXGRQDNQ?" target="_blank" rel="nofollow" data-dimension112="4a992634-cdfb-11f1-95b6-d1b60e3eb69b" data-action="Deal Block" data-label="Talisa Espadrilles for Women" data-dimension48="Talisa Espadrilles for Women" data-dimension25="$37">View Deal</a></p></div><div class="product"><a data-dimension112="5a29d898-cba6-11f1-934d-13d0e2030136" data-action="Deal Block" data-label="Laz Cork Footbed Sandals" data-dimension48="Laz Cork Footbed Sandals" data-dimension25="$39" href="https://www.amazon.com/dp/B0H8FB19F7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:606px;"><p class="vanilla-image-block" style="padding-top:114.69%;"><img id="GknzxZr7RhbEEsFqQG3HjN" name="Laz" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/GknzxZr7RhbEEsFqQG3HjN-1920-80.jpg" mos="" align="middle" fullscreen="" width="606" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0H8FB19F7" target="_blank" rel="nofollow" data-dimension112="5a29d898-cba6-11f1-934d-13d0e2030136" data-action="Deal Block" data-label="Laz Cork Footbed Sandals" data-dimension48="Laz Cork Footbed Sandals" data-dimension25="$39">Laz Cork Footbed Sandals: was $59 now $39</a></strong><br />If you're in the market for some Birkenstocks but don't want to pay the hefty price, these Cushionaire sandals are the next best thing. Crafted from high-quality faux leather, the sandals feature a soft lining and adjustable double buckle strap. They're also available in a plethora of colors, although price may vary. <a class="view-deal button" href="https://www.amazon.com/dp/B0H8FB19F7" target="_blank" rel="nofollow" data-dimension112="5a29d898-cba6-11f1-934d-13d0e2030136" data-action="Deal Block" data-label="Laz Cork Footbed Sandals" data-dimension48="Laz Cork Footbed Sandals" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="5a29d8fc-cba6-11f1-893c-4df15183fb6f" data-action="Deal Block" data-label="Lens Sandals" data-dimension48="Lens Sandals" data-dimension25="$49" href="https://www.amazon.com/dp/B0GZJ8VB6M" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:543px;"><p class="vanilla-image-block" style="padding-top:127.99%;"><img id="v9a622fikJvyBJaGFHRcpH" name="Cushionaire Lens" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/v9a622fikJvyBJaGFHRcpH-1920-80.jpg" mos="" align="middle" fullscreen="" width="543" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0GZJ8VB6M" target="_blank" rel="nofollow" data-dimension112="5a29d8fc-cba6-11f1-893c-4df15183fb6f" data-action="Deal Block" data-label="Lens Sandals" data-dimension48="Lens Sandals" data-dimension25="$49">Lens Sandals: was $69 now $49</a></strong><br />Looking for a fun little twist on a classic slide? Slip into these comfortable sandals that feature unique braided straps. They have a cushioned footbed and a contoured sole making them extra comfy. They also pair nicely with dresses, denim and casual outfits.<a class="view-deal button" href="https://www.amazon.com/dp/B0GZJ8VB6M" target="_blank" rel="nofollow" data-dimension112="5a29d8fc-cba6-11f1-893c-4df15183fb6f" data-action="Deal Block" data-label="Lens Sandals" data-dimension48="Lens Sandals" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="5a29d9c4-cba6-11f1-bc65-41b830e20f20" data-action="Deal Block" data-label="Missy Mary Jane Ballet Flats" data-dimension48="Missy Mary Jane Ballet Flats" data-dimension25="$49" href="https://www.amazon.com/dp/B0GYXT459Z?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:534px;"><p class="vanilla-image-block" style="padding-top:130.15%;"><img id="ZXhLhPRFgdWuUD2Keq2vQj" name="Cushionaire mary jane" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZXhLhPRFgdWuUD2Keq2vQj-1920-80.jpg" mos="" align="middle" fullscreen="" width="534" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0GYXT459Z?" target="_blank" rel="nofollow" data-dimension112="5a29d9c4-cba6-11f1-bc65-41b830e20f20" data-action="Deal Block" data-label="Missy Mary Jane Ballet Flats" data-dimension48="Missy Mary Jane Ballet Flats" data-dimension25="$49">Missy Mary Jane Ballet Flats: was $69 now $49</a></strong><br />Classic Mary Janes meet sophisticated ballet flats in this shoe that is lightweight, soft and flexible. They're great for everyday wear and even though they feature a velvet material, they are breathable. <a class="view-deal button" href="https://www.amazon.com/dp/B0GYXT459Z?" target="_blank" rel="nofollow" data-dimension112="5a29d9c4-cba6-11f1-bc65-41b830e20f20" data-action="Deal Block" data-label="Missy Mary Jane Ballet Flats" data-dimension48="Missy Mary Jane Ballet Flats" data-dimension25="$49">View Deal</a></p></div><h3 class="article-body__section" id="section-new-balance"><span>New Balance</span></h3><div class="product"><a data-dimension112="5a29da96-cba6-11f1-b25d-7f9ebe944c8c" data-action="Deal Block" data-label="515 Sneaker (Women's)" data-dimension48="515 Sneaker (Women's)" data-dimension25="$55" href="https://www.amazon.com/New-Balance-Sneaker-Reflection-Aluminum/dp/B09YBLCL41" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:747px;"><p class="vanilla-image-block" style="padding-top:57.30%;"><img id="twUFoFTRbcG9RAJR2CTDER" name="515 Sneaker (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/twUFoFTRbcG9RAJR2CTDER-1920-80.jpg" mos="" align="middle" fullscreen="" width="747" height="428" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-Sneaker-Reflection-Aluminum/dp/B09YBLCL41" target="_blank" rel="nofollow" data-dimension112="5a29da96-cba6-11f1-b25d-7f9ebe944c8c" data-action="Deal Block" data-label="515 Sneaker (Women's)" data-dimension48="515 Sneaker (Women's)" data-dimension25="$55">515 Sneaker (Women's): was $79 now $55</a></strong><br />Featuring an understated style in a wide selection of colors, the New Balance 515 sneakers are a wardrobe staple. The upper is made of a mix of suede and mesh, and the soles provide all-day comfort.<a class="view-deal button" href="https://www.amazon.com/New-Balance-Sneaker-Reflection-Aluminum/dp/B09YBLCL41" target="_blank" rel="nofollow" data-dimension112="5a29da96-cba6-11f1-b25d-7f9ebe944c8c" data-action="Deal Block" data-label="515 Sneaker (Women's)" data-dimension48="515 Sneaker (Women's)" data-dimension25="$55">View Deal</a></p></div><div class="product"><a data-dimension112="5a29db04-cba6-11f1-b343-9367060aa4f8" data-action="Deal Block" data-label="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension48="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension25="$98" href="https://www.amazon.com/New-Balance-FuelCell-Walking-Electric/dp/B0D2Y7L3DC" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:755px;"><p class="vanilla-image-block" style="padding-top:55.23%;"><img id="ufsfox6NerPUoEY6YYZYXk" name="FuelCell Walker Elite V1 Walking Shoe (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ufsfox6NerPUoEY6YYZYXk-1920-80.jpg" mos="" align="middle" fullscreen="" width="755" height="417" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-FuelCell-Walking-Electric/dp/B0D2Y7L3DC" target="_blank" rel="nofollow" data-dimension112="5a29db04-cba6-11f1-b343-9367060aa4f8" data-action="Deal Block" data-label="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension48="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension25="$98">FuelCell Walker Elite V1 Walking Shoe (Women's): was $139 now $98</a></strong><br />Engineered for walking, the New Balance FuelCell Walker Elite V1 Walking Shoes are cushioned, stable, and propel your feet forward with each step. They look super sleek, too. <a class="view-deal button" href="https://www.amazon.com/New-Balance-FuelCell-Walking-Electric/dp/B0D2Y7L3DC" target="_blank" rel="nofollow" data-dimension112="5a29db04-cba6-11f1-b343-9367060aa4f8" data-action="Deal Block" data-label="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension48="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension25="$98">View Deal</a></p></div><h3 class="article-body__section" id="section-dr-martens"><span>Dr Martens</span></h3><div class="product"><a data-dimension112="6efccfcc-cba7-11f1-ac8b-4364d76bdba0" data-action="Deal Block" data-label="Sanguine Leather Chelsea Boot (Women's)" data-dimension48="Sanguine Leather Chelsea Boot (Women's)" data-dimension25="$119" href="https://www.amazon.com/Dr-Martens-Sanguine-Leather-Chelsea/dp/B0FFGHQ3L4" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:622px;"><p class="vanilla-image-block" style="padding-top:111.74%;"><img id="jBsVYKGReMs9YKKMZkCkBC" name="Sanguine Leather Chelsea Boot (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jBsVYKGReMs9YKKMZkCkBC-1920-80.jpg" mos="" align="middle" fullscreen="" width="622" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Dr-Martens-Sanguine-Leather-Chelsea/dp/B0FFGHQ3L4" target="_blank" rel="nofollow" data-dimension112="6efccfcc-cba7-11f1-ac8b-4364d76bdba0" data-action="Deal Block" data-label="Sanguine Leather Chelsea Boot (Women's)" data-dimension48="Sanguine Leather Chelsea Boot (Women's)" data-dimension25="$119">Sanguine Leather Chelsea Boot (Women's): was $135 now $119</a></strong><br />Nothing screams "fall" more than a Chelsea boot. Coming from Dr Martens, this pair is extra-durable and has a water resistant coating. Not only does the pull tab make them stand out — it makes them easier to put on!<a class="view-deal button" href="https://www.amazon.com/Dr-Martens-Sanguine-Leather-Chelsea/dp/B0FFGHQ3L4" target="_blank" rel="nofollow" data-dimension112="6efccfcc-cba7-11f1-ac8b-4364d76bdba0" data-action="Deal Block" data-label="Sanguine Leather Chelsea Boot (Women's)" data-dimension48="Sanguine Leather Chelsea Boot (Women's)" data-dimension25="$119">View Deal</a></p></div><div class="product"><a data-dimension112="6efcd03a-cba7-11f1-ace3-ad0127b6787f" data-action="Deal Block" data-label="1460 8 Eye Boot (Unisex)" data-dimension48="1460 8 Eye Boot (Unisex)" data-dimension25="$153" href="https://www.amazon.com/Dr-Martens-Smooth-Combat-Womens/dp/B004SI1QNU/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:684px;"><p class="vanilla-image-block" style="padding-top:101.61%;"><img id="imnJnaGkotNWgHnjsGETSk" name="1460 8 Eye Boot" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/imnJnaGkotNWgHnjsGETSk-1920-80.jpg" mos="" align="middle" fullscreen="" width="684" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Dr-Martens-Smooth-Combat-Womens/dp/B004SI1QNU/" target="_blank" rel="nofollow" data-dimension112="6efcd03a-cba7-11f1-ace3-ad0127b6787f" data-action="Deal Block" data-label="1460 8 Eye Boot (Unisex)" data-dimension48="1460 8 Eye Boot (Unisex)" data-dimension25="$153">1460 8 Eye Boot (Unisex): was $180 now $153</a></strong><br />Right now Dr. Martens’ 1460 8 Eye Boots have seen a discount at Amazon. Made of vegan leather, their slip-resistant soles and tough construction make them great for both work and everyday wear.<a class="view-deal button" href="https://www.amazon.com/Dr-Martens-Smooth-Combat-Womens/dp/B004SI1QNU/" target="_blank" rel="nofollow" data-dimension112="6efcd03a-cba7-11f1-ace3-ad0127b6787f" data-action="Deal Block" data-label="1460 8 Eye Boot (Unisex)" data-dimension48="1460 8 Eye Boot (Unisex)" data-dimension25="$153">View Deal</a></p></div><h3 class="article-body__section" id="section-timberland"><span>Timberland</span></h3><div class="product"><a data-dimension112="49e34d5a-cba8-11f1-b931-cdf54df1eceb" data-action="Deal Block" data-label="Davis Square Chukka Shoe (Men's)" data-dimension48="Davis Square Chukka Shoe (Men's)" data-dimension25="$48" href="https://www.amazon.com/Timberland-Davis-Square-Chukka-Wheat/dp/B0D54GMPLS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:895px;"><p class="vanilla-image-block" style="padding-top:77.65%;"><img id="9sA8mqcAuQkkDAVnQjVBqj" name="Davis Square Chukka Shoe (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/9sA8mqcAuQkkDAVnQjVBqj-1920-80.jpg" mos="" align="middle" fullscreen="" width="895" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Timberland-Davis-Square-Chukka-Wheat/dp/B0D54GMPLS" target="_blank" rel="nofollow" data-dimension112="49e34d5a-cba8-11f1-b931-cdf54df1eceb" data-action="Deal Block" data-label="Davis Square Chukka Shoe (Men's)" data-dimension48="Davis Square Chukka Shoe (Men's)" data-dimension25="$48">Davis Square Chukka Shoe (Men's): was $95 now $48</a></strong><br />Classic, stylish and comfortable. It doesn't get better than the Davis Square Chukka Shoe — especially when you can get a pair for almost half off. These are made of premium Timberland leather and have comfortable OrthoLite insoles.<a class="view-deal button" href="https://www.amazon.com/Timberland-Davis-Square-Chukka-Wheat/dp/B0D54GMPLS" target="_blank" rel="nofollow" data-dimension112="49e34d5a-cba8-11f1-b931-cdf54df1eceb" data-action="Deal Block" data-label="Davis Square Chukka Shoe (Men's)" data-dimension48="Davis Square Chukka Shoe (Men's)" data-dimension25="$48">View Deal</a></p></div><div class="product"><a data-dimension112="49e34dd2-cba8-11f1-9bca-6150122cd4a8" data-action="Deal Block" data-label="Linden Woods 6-Inch Waterproof Boot (Women's)" data-dimension48="Linden Woods 6-Inch Waterproof Boot (Women's)" data-dimension25="$111" href="https://www.amazon.com/Timberland-Womens-Waterproof-Fashion-Black-New/dp/B0D47QK4VT" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:605px;"><p class="vanilla-image-block" style="padding-top:114.88%;"><img id="mW6fWKfX39uKuvWZUuMbnA" name="Linden Woods 6-Inch Waterproof Boot (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/mW6fWKfX39uKuvWZUuMbnA-1920-80.jpg" mos="" align="middle" fullscreen="" width="605" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Timberland-Womens-Waterproof-Fashion-Black-New/dp/B0D47QK4VT" target="_blank" rel="nofollow" data-dimension112="49e34dd2-cba8-11f1-9bca-6150122cd4a8" data-action="Deal Block" data-label="Linden Woods 6-Inch Waterproof Boot (Women's)" data-dimension48="Linden Woods 6-Inch Waterproof Boot (Women's)" data-dimension25="$111">Linden Woods 6-Inch Waterproof Boot (Women's): was $140 now $111</a></strong><br />These ankle boots offer versatility, function — and protection for the elements. Not only are they stylish, but they also have rubber lug outsoles for excellent traction and grip on slippery surfaces. <a class="view-deal button" href="https://www.amazon.com/Timberland-Womens-Waterproof-Fashion-Black-New/dp/B0D47QK4VT" target="_blank" rel="nofollow" data-dimension112="49e34dd2-cba8-11f1-9bca-6150122cd4a8" data-action="Deal Block" data-label="Linden Woods 6-Inch Waterproof Boot (Women's)" data-dimension48="Linden Woods 6-Inch Waterproof Boot (Women's)" data-dimension25="$111">View Deal</a></p></div><h3 class="article-body__section" id="section-asics"><span>Asics</span></h3><div class="product"><a data-dimension112="5a29dbd6-cba6-11f1-98f1-1d2e557f423c" data-action="Deal Block" data-label="Tiger Runner II (Women's)" data-dimension48="Tiger Runner II (Women's)" data-dimension25="$59" href="https://www.amazon.com/ASICS-Womens-Runner-Sportstyle-Silver/dp/B0H3F1WSB3" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:682px;"><p class="vanilla-image-block" style="padding-top:75.07%;"><img id="vcT4ZrTkbB5kx6uGRWjquJ" name="asics tiger runner ii" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vcT4ZrTkbB5kx6uGRWjquJ-1920-80.png" mos="" align="middle" fullscreen="" width="682" height="512" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Runner-Sportstyle-Silver/dp/B0H3F1WSB3" target="_blank" rel="nofollow" data-dimension112="5a29dbd6-cba6-11f1-98f1-1d2e557f423c" data-action="Deal Block" data-label="Tiger Runner II (Women's)" data-dimension48="Tiger Runner II (Women's)" data-dimension25="$59">Tiger Runner II (Women's): was $85 now $59</a></strong><br />Designed for everyday wear, these Asics sneakers are inspired by classic 80s jogging shoes. On the inside, they're packed with today's best cushioning and durability.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Runner-Sportstyle-Silver/dp/B0H3F1WSB3" target="_blank" rel="nofollow" data-dimension112="5a29dbd6-cba6-11f1-98f1-1d2e557f423c" data-action="Deal Block" data-label="Tiger Runner II (Women's)" data-dimension48="Tiger Runner II (Women's)" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="5a29dc3a-cba6-11f1-a90c-53047959208b" data-action="Deal Block" data-label="Gel-Venture 11" data-dimension48="Gel-Venture 11" data-dimension25="$69" href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Carrier/dp/B0FV72G49S" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1146px;"><p class="vanilla-image-block" style="padding-top:75.04%;"><img id="44i7uWA8WvTqRemkvKZpV6" name="Gel-Venture 11" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/44i7uWA8WvTqRemkvKZpV6-1920-80.jpg" mos="" align="middle" fullscreen="" width="1146" height="860" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Asics Gel-Venture 11 are designed for everyday runs and walks! They have Amplifoam Plus midsole cushioning on board, and a 2mm higher stack height — 2mm of extra softness to absorb impact and keep you comfortable for hours.<a class="view-deal button" href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Carrier/dp/B0FV72G49S" target="_blank" rel="nofollow" data-dimension112="5a29dc3a-cba6-11f1-a90c-53047959208b" data-action="Deal Block" data-label="Gel-Venture 11" data-dimension48="Gel-Venture 11" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="5a29dc9e-cba6-11f1-95a5-ff83973278af" data-action="Deal Block" data-label="Gel-K1011 Sneakers (Men's)" data-dimension48="Gel-K1011 Sneakers (Men's)" data-dimension25="$99" href="https://www.asics.com/us/en-us/gel-k1011/p/ANA_1203A830-003.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:683px;"><p class="vanilla-image-block" style="padding-top:74.96%;"><img id="iyit4YAmvDQPwsHoyfwz4f" name="Gel-K1011 Shoes" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/iyit4YAmvDQPwsHoyfwz4f-1920-80.webp" mos="" align="middle" fullscreen="" width="683" height="512" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.asics.com/us/en-us/gel-k1011/p/ANA_1203A830-003.html" target="_blank" rel="nofollow" data-dimension112="5a29dc9e-cba6-11f1-95a5-ff83973278af" data-action="Deal Block" data-label="Gel-K1011 Sneakers (Men's)" data-dimension48="Gel-K1011 Sneakers (Men's)" data-dimension25="$99">Gel-K1011 Sneakers (Men's): was $140 now $99</a></strong><br />An iconic design and reliable comfort, what more could you want from a pair of sneakers? It takes cues from some of Asics' best shoes, with Gel-Kayano-inspired panels on the upper and the same midsole tooling system as the Gel-Cumulus 17.<a class="view-deal button" href="https://www.asics.com/us/en-us/gel-k1011/p/ANA_1203A830-003.html" target="_blank" rel="nofollow" data-dimension112="5a29dc9e-cba6-11f1-95a5-ff83973278af" data-action="Deal Block" data-label="Gel-K1011 Sneakers (Men's)" data-dimension48="Gel-K1011 Sneakers (Men's)" data-dimension25="$99">View Deal</a></p></div><h3 class="article-body__section" id="section-hoka"><span>Hoka</span></h3><div class="product"><a data-dimension112="5a29dd66-cba6-11f1-96f7-77a3c98b8bcd" data-action="Deal Block" data-label="Skyflow (Men's)" data-dimension48="Skyflow (Men's)" data-dimension25="$112" href="https://www.hoka.com/en/us/mens-everyday-running-shoes/skyflow/1155111.html?dwvar_1155111_color=SRYS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1932px;"><p class="vanilla-image-block" style="padding-top:81.11%;"><img id="WvCZL3SYYevA9hGSrJNCDD" name="Hoka skyflow" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/WvCZL3SYYevA9hGSrJNCDD-1920-80.jpg" mos="" align="middle" fullscreen="" width="1932" height="1567" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/mens-everyday-running-shoes/skyflow/1155111.html?dwvar_1155111_color=SRYS" target="_blank" rel="nofollow" data-dimension112="5a29dd66-cba6-11f1-96f7-77a3c98b8bcd" data-action="Deal Block" data-label="Skyflow (Men's)" data-dimension48="Skyflow (Men's)" data-dimension25="$112">Skyflow (Men's): was $160 now $112</a></strong><br />The Hoka Skyflow is a comfortable, cushioned running shoe with a midsole made from a lightweight supercritical EVA foam. It's a protective shoe that's also quite versatile, and a good option for walking and runners of all levels.<a class="view-deal button" href="https://www.hoka.com/en/us/mens-everyday-running-shoes/skyflow/1155111.html?dwvar_1155111_color=SRYS" target="_blank" rel="nofollow" data-dimension112="5a29dd66-cba6-11f1-96f7-77a3c98b8bcd" data-action="Deal Block" data-label="Skyflow (Men's)" data-dimension48="Skyflow (Men's)" data-dimension25="$112">View Deal</a></p></div><div class="product"><a data-dimension112="5a29ddd4-cba6-11f1-99c5-e724d8a99ce9" data-action="Deal Block" data-label="Clifton 10 (Men's)" data-dimension48="Clifton 10 (Men's)" data-dimension25="$124" href="https://www.hoka.com/en/us/mens-everyday-running-gear/clifton-10/1162030.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2220px;"><p class="vanilla-image-block" style="padding-top:81.13%;"><img id="MKZ2WmvKiUZp3LodsbSF47" name="Hoka Clifton 10" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/MKZ2WmvKiUZp3LodsbSF47-1920-80.png" mos="" align="middle" fullscreen="" width="2220" height="1801" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/mens-everyday-running-gear/clifton-10/1162030.html" target="_blank" rel="nofollow" data-dimension112="5a29ddd4-cba6-11f1-99c5-e724d8a99ce9" data-action="Deal Block" data-label="Clifton 10 (Men's)" data-dimension48="Clifton 10 (Men's)" data-dimension25="$124">Clifton 10 (Men's): was $155 now $124</a></strong><br />The <a href="https://www.tomsguide.com/wellness/running/ive-tested-nearly-every-hoka-running-shoe-these-are-my-3-top-picks">Hoka Clifton 10</a> is one of the most popular running shoes from any brand, and a top option for newer runners in particular. It's comfortable, but pretty lightweight, and enjoyable for easy and fast training runs. This is another shoe that's not due for a big update in 2026, so don't wait for the Clifton 11; bag this deal instead.<a class="view-deal button" href="https://www.hoka.com/en/us/mens-everyday-running-gear/clifton-10/1162030.html" target="_blank" rel="nofollow" data-dimension112="5a29ddd4-cba6-11f1-99c5-e724d8a99ce9" data-action="Deal Block" data-label="Clifton 10 (Men's)" data-dimension48="Clifton 10 (Men's)" data-dimension25="$124">View Deal</a></p></div><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Home+Appliances&amp;view_mode=savings_squad&amp;widget_title=Top+Deals+Handpicked+by+Our+Editors&amp;widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&amp;bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                if (externalUrl) {                   if (seenUrls.has(externalUrl)) return;                  seenUrls.add(externalUrl);                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || '',                   authorName: article.articleauthortext ? article.articleauthortext[0] : (article.articleauthor ? article.articleauthor[0] : ''),                   authorRole: article.articleauthorrole ? article.articleauthorrole[0] : '',                   authorImage: article.articleauthormedia ? article.articleauthormedia[0] : '',                   documentUrl: article.documenturl ? article.documenturl[0] : '',                   modifiedDate: article.contentmodifieddate || article.modifieddate || ''                });             });          });                    const airedaleBrandsList = Object.keys(overallBrandsCounts).map(b => ({              formatted_value: b,              count: overallBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness/21-fall-walking-shoe-deals-biggest-savings-with-up-to-61-percent-off-skechers-birkenstocks-and-new-balance</link>
                                                                            <description>
                            <![CDATA[ I'm sharing the best walking shoe deals on the biggest brands, including Skechers, Birkenstocks and more. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">RVKvhokmpzjBDUwK4cEY4J</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/yFaeiDguFLf5wJAy3GUFzQ-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 19 Oct 2026 10:41:29 +0000</pubDate>                                                                                                                                <updated>Thu, 22 Oct 2026 10:17:01 +0000</updated>
                                                                                                                                            <category><![CDATA[Fitness]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                <author><![CDATA[ millie.daviswilliams@futurenet.com (Millie Davis-Williams) ]]></author>                    <dc:creator><![CDATA[ Millie Davis-Williams ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/WU6pa7hKuxs5ScCoqcXYWA-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Millie is a Deals Editor at Tom&#039;s Guide specializing in tech deals content. Based in London, Millie has spent a lifetime stubbornly refusing to pay full price on any possible purchase. She has years of searching for the best discounts on the latest and greatest phones, TVs and gadgets under her belt, and knows how to sort the best deals from the rest. Helping readers save on the products they want is her mission, whether it’s an Apple Watch or a new tablet.&lt;/p&gt;&lt;p&gt;Since working at Tom’s Guide, Millie has covered retail events like Prime Day, Black Friday and Cyber Monday extensively, meaning she knows the products readers are looking for and the best times of year to hit “purchase.”&lt;/p&gt;&lt;p&gt;When she’s not looking for discounts, Millie covers news and writes how-to articles about everything from phones, streaming devices, and headphones to apps and video games.&lt;/p&gt;&lt;p&gt;In her spare time, Millie enjoys reading, gaming on her Nintendo Switch and creating digital art. She’s also a fan of watching Disney movies and collecting plush (the latter having totally taken over her bedroom.)&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/yFaeiDguFLf5wJAy3GUFzQ-1920-80.jpg">
                                                            <media:credit><![CDATA[Skechers]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Skechers Go Walk Flex walking shoes]]></media:description>                                                            <media:text><![CDATA[Skechers Go Walk Flex walking shoes]]></media:text>
                                <media:title type="plain"><![CDATA[Skechers Go Walk Flex walking shoes]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/yFaeiDguFLf5wJAy3GUFzQ-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Enjoying the fall weather? To make your walks even more enjoyable, you can save a bunch on best selling walking shoes right now. There are discounts to be found on everything from Skechers slip-ins to comfortable Birkenstock sandals.</p><p>Right now <a href="https://www.amazon.com/b?node=211953829011&amp;ref_=shoes&amp;pf_rd_p=b017f2eb-1ce1-408d-8152-3fb62c1c7cbe&amp;pf_rd_r=T1P1PSA2E0E72KS74A8H" target="_blank" rel="nofollow">Amazon is offering deals on boots, mules, cozy slippers and more</a>. I'm also a fan of <a href="https://www.asics.com/us/en-us/sportstyle-clearance/c/aa11015000/" target="_blank" rel="nofollow">Asics current sale</a> as there are plenty of Sportstyle sneakers available at a lower price than usual.</p><p><strong>Note: </strong>prices can vary depending on the size and color you select. To find the best deals, check out the different colors available in your size.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links </span></h3><ul><li><strong>Asics: </strong><a href="https://www.asics.com/us/en-us/clearance/c/aa60000000/?" target="_blank" rel="nofollow"><strong>deals from $49</strong></a></li><li><strong>Brooks: </strong><a href="https://www.amazon.com/stores/Brooks/page/B6834DFA-396F-4E38-98F6-3D2739393271?" target="_blank" rel="nofollow"><strong>up to 40% off</strong></a></li><li><strong>Hoka: </strong><a href="https://www.hoka.com/en/us/sale/" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li><li><strong>Nike: </strong><a href="https://www.nike.com/w/mens-shoes-nik1zy7ok" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li><li><strong>New Balance: </strong><a href="https://www.amazon.com/stores/NewBalanceAthleticShoeInc/page/855D4CDF-ADB7-4BE8-9E26-A085D029E4B5" target="_blank" rel="nofollow"><strong>deals from $39</strong></a></li><li><strong>Skechers: </strong><a href="https://www.skechers.com/women/shop-by-activity/walking/" target="_blank" rel="nofollow"><strong>20% off for members</strong></a></li></ul><h3 class="article-body__section" id="section-skechers"><span>Skechers</span></h3><div class="product"><a data-dimension112="5a29d47e-cba6-11f1-aad6-a7ffa4f1850d" data-action="Deal Block" data-label="Refine 2.0 Nora (Women's)" data-dimension48="Refine 2.0 Nora (Women's)" data-dimension25="$32" href="https://www.amazon.com/Skechers-Womens-Sport-Active-Refine/dp/B0G1PK31X7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:66.91%;"><img id="XtYccaXnTY5XF946soUYSE" name="Refine 2.0 Nora (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XtYccaXnTY5XF946soUYSE-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="465" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Sport-Active-Refine/dp/B0G1PK31X7" target="_blank" rel="nofollow" data-dimension112="5a29d47e-cba6-11f1-aad6-a7ffa4f1850d" data-action="Deal Block" data-label="Refine 2.0 Nora (Women's)" data-dimension48="Refine 2.0 Nora (Women's)" data-dimension25="$32">Refine 2.0 Nora (Women's): was $84 now $32</a></strong><br />These Skechers have seen an impressive $52 discount. Incredibly easy to wear, they feature a stretch knit upper, arch-fit insoles and are machine washable. The neutral design makes them easy to style, too.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Sport-Active-Refine/dp/B0G1PK31X7" target="_blank" rel="nofollow" data-dimension112="5a29d47e-cba6-11f1-aad6-a7ffa4f1850d" data-action="Deal Block" data-label="Refine 2.0 Nora (Women's)" data-dimension48="Refine 2.0 Nora (Women's)" data-dimension25="$32">View Deal</a></p></div><div class="product"><a data-dimension112="b35519ba-cd30-11f1-be57-83d526322683" data-action="Deal Block" data-label="Flex Appeal 4.0-Livin' in This Sport Sandal (Women's)" data-dimension48="Flex Appeal 4.0-Livin' in This Sport Sandal (Women's)" data-dimension25="$41" href="https://www.amazon.com/Skechers-Womens-Appeal-4-0-Livin-Sandal/dp/B0CDKP7SL6" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:63.88%;"><img id="hvAgkNmHzWtvwtfLxAYGpQ" name="Flex Appeal 4.0-Livin' in This Sport Sandal (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hvAgkNmHzWtvwtfLxAYGpQ-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="444" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Appeal-4-0-Livin-Sandal/dp/B0CDKP7SL6" target="_blank" rel="nofollow" data-dimension112="b35519ba-cd30-11f1-be57-83d526322683" data-action="Deal Block" data-label="Flex Appeal 4.0-Livin' in This Sport Sandal (Women's)" data-dimension48="Flex Appeal 4.0-Livin' in This Sport Sandal (Women's)" data-dimension25="$41">Flex Appeal 4.0-Livin' in This Sport Sandal (Women's): was $49 now $41</a></strong><br />These Skechers sandals have seen significant discounts in certain sizes and colors, so grab a pair and put them away for next summer! These have a super soft Yoga Foam sole and unlike most sandals, stay securely on your feet thanks to their stretchy knit upper.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Appeal-4-0-Livin-Sandal/dp/B0CDKP7SL6" target="_blank" rel="nofollow" data-dimension112="b35519ba-cd30-11f1-be57-83d526322683" data-action="Deal Block" data-label="Flex Appeal 4.0-Livin' in This Sport Sandal (Women's)" data-dimension48="Flex Appeal 4.0-Livin' in This Sport Sandal (Women's)" data-dimension25="$41">View Deal</a></p></div><div class="product"><a data-dimension112="b57f113a-cc6a-11f1-a899-c1f010793431" data-action="Deal Block" data-label="Flex Adapt Juliette (Women's)" data-dimension48="Flex Adapt Juliette (Women's)" data-dimension25="$42" href="https://www.amazon.com/Skechers-Womens-Slip-Loafer-Black/dp/B0FG9VLFZM" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:64.89%;"><img id="j8oCtLFQLWPvQmWbeNMJU9" name="Flex Adapt Juliette (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/j8oCtLFQLWPvQmWbeNMJU9-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="451" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Slip-Loafer-Black/dp/B0FG9VLFZM" target="_blank" rel="nofollow" data-dimension112="b57f113a-cc6a-11f1-a899-c1f010793431" data-action="Deal Block" data-label="Flex Adapt Juliette (Women's)" data-dimension48="Flex Adapt Juliette (Women's)" data-dimension25="$42">Flex Adapt Juliette (Women's): was $79 now $42</a></strong><br />This discount is available in limited sizes and colors, so make sure to grab it if it's available in your size. The Skechers Flex Adapt Juliette have a super-simple and sweet look that's very easy to style, and even easier to wear. The stretch knit upper feels just like a comfy pair of socks.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Slip-Loafer-Black/dp/B0FG9VLFZM" target="_blank" rel="nofollow" data-dimension112="b57f113a-cc6a-11f1-a899-c1f010793431" data-action="Deal Block" data-label="Flex Adapt Juliette (Women's)" data-dimension48="Flex Adapt Juliette (Women's)" data-dimension25="$42">View Deal</a></p></div><div class="product"><a data-dimension112="5a29d4ec-cba6-11f1-b115-d7a225eed3a8" data-action="Deal Block" data-label="Sloan Slip-In Sneakers (Men's)" data-dimension48="Sloan Slip-In Sneakers (Men's)" data-dimension25="$43" href="https://www.amazon.com/Skechers-Knitted-Bungee-Slip-Sneakers/dp/B0FNLWG66B/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:69.21%;"><img id="nYRVX4hTE2gNxHqkbBmWTG" name="Sloan Slip-In Sneakers (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/nYRVX4hTE2gNxHqkbBmWTG-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="481" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Knitted-Bungee-Slip-Sneakers/dp/B0FNLWG66B/" target="_blank" rel="nofollow" data-dimension112="5a29d4ec-cba6-11f1-b115-d7a225eed3a8" data-action="Deal Block" data-label="Sloan Slip-In Sneakers (Men's)" data-dimension48="Sloan Slip-In Sneakers (Men's)" data-dimension25="$43">Sloan Slip-In Sneakers (Men's): was $85 now $43</a></strong><br />You can save 49% on the Skechers Sloan for a limited time, so if it's in stock in your size, don't miss it! The brown-and-orange colorway is super stylish, and you get a visible air cushion unit at the side.<a class="view-deal button" href="https://www.amazon.com/Skechers-Knitted-Bungee-Slip-Sneakers/dp/B0FNLWG66B/" target="_blank" rel="nofollow" data-dimension112="5a29d4ec-cba6-11f1-b115-d7a225eed3a8" data-action="Deal Block" data-label="Sloan Slip-In Sneakers (Men's)" data-dimension48="Sloan Slip-In Sneakers (Men's)" data-dimension25="$43">View Deal</a></p></div><div class="product"><a data-dimension112="5a29d550-cba6-11f1-b886-4f7ac3077f2e" data-action="Deal Block" data-label="Wilshire Blvd Knit Sail (Women's)" data-dimension48="Wilshire Blvd Knit Sail (Women's)" data-dimension25="$45" href="https://www.amazon.com/Skechers-Womens-Slip-Boat-White/dp/B0D9PMGCTG" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1006px;"><p class="vanilla-image-block" style="padding-top:69.09%;"><img id="K2ZyHfXK9RpXVL5s5syuw6" name="Wilshire Blvd Knit Sail (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/K2ZyHfXK9RpXVL5s5syuw6-1920-80.jpg" mos="" align="middle" fullscreen="" width="1006" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Slip-Boat-White/dp/B0D9PMGCTG" target="_blank" rel="nofollow" data-dimension112="5a29d550-cba6-11f1-b886-4f7ac3077f2e" data-action="Deal Block" data-label="Wilshire Blvd Knit Sail (Women's)" data-dimension48="Wilshire Blvd Knit Sail (Women's)" data-dimension25="$45">Wilshire Blvd Knit Sail (Women's): was $70 now $45</a></strong><br />These knitted Skechers give off the perfect cozy vibe for fall. They don't even feel like wearing shoes — Skechers says they provide socklike comfort. I especially adore the bow detail on the toe. <a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Slip-Boat-White/dp/B0D9PMGCTG" target="_blank" rel="nofollow" data-dimension112="5a29d550-cba6-11f1-b886-4f7ac3077f2e" data-action="Deal Block" data-label="Wilshire Blvd Knit Sail (Women's)" data-dimension48="Wilshire Blvd Knit Sail (Women's)" data-dimension25="$45">View Deal</a></p></div><div class="product"><a data-dimension112="b3551a5a-cd30-11f1-91b4-a3ae6bc157d3" data-action="Deal Block" data-label="Cleo Bewitch Ballet Flat (Women's)" data-dimension48="Cleo Bewitch Ballet Flat (Women's)" data-dimension25="$46" href="https://www.amazon.com/Skechers-Womens-Bewitch-Ballet-Black/dp/B08L5J6N5X" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:872px;"><p class="vanilla-image-block" style="padding-top:33.26%;"><img id="4zHiCZtnHGSthG3GrZpZw4" name="516NWIhEd8L._AC_SY695_.jpg" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4zHiCZtnHGSthG3GrZpZw4-1920-80.jpg" mos="" align="middle" fullscreen="" width="872" height="290" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Womens-Bewitch-Ballet-Black/dp/B08L5J6N5X" target="_blank" rel="nofollow" data-dimension112="b3551a5a-cd30-11f1-91b4-a3ae6bc157d3" data-action="Deal Block" data-label="Cleo Bewitch Ballet Flat (Women's)" data-dimension48="Cleo Bewitch Ballet Flat (Women's)" data-dimension25="$46">Cleo Bewitch Ballet Flat (Women's): was $49 now $46</a></strong><br />For a sleek, comfortable pair of shoes, try these Skechers Cleo Bewitch Ballet Flats. They feature Skechers Air Cooled Memory Foam soles, and breathable stretch knit uppers. Reviewers on Amazon say these shoes go with everything and can be worn all day.<a class="view-deal button" href="https://www.amazon.com/Skechers-Womens-Bewitch-Ballet-Black/dp/B08L5J6N5X" target="_blank" rel="nofollow" data-dimension112="b3551a5a-cd30-11f1-91b4-a3ae6bc157d3" data-action="Deal Block" data-label="Cleo Bewitch Ballet Flat (Women's)" data-dimension48="Cleo Bewitch Ballet Flat (Women's)" data-dimension25="$46">View Deal</a></p></div><div class="product"><a data-dimension112="5a29d5be-cba6-11f1-bd2f-798e978702b7" data-action="Deal Block" data-label="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension48="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension25="$57" href="https://www.amazon.com/Skechers-Mens-Walk-Flex-Hands-Sneaker/dp/B0CFN8VR99" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:54.68%;"><img id="DsBvJExJKzNCdDFDnDXn3T" name="71y3Wpz-YFL._AC_SX695_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/DsBvJExJKzNCdDFDnDXn3T-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="380" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Skechers-Mens-Walk-Flex-Hands-Sneaker/dp/B0CFN8VR99" target="_blank" rel="nofollow" data-dimension112="5a29d5be-cba6-11f1-bd2f-798e978702b7" data-action="Deal Block" data-label="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension48="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension25="$57">Slip-Ins Go Walk Flex Hands Up Sneaker: was $84 now $57</a></strong><br />A comfortable, reliable shoe, the Skechers Go Walk Flex Hands Up are now on sale starting from just $57. These come in a range of muted shades, meaning they're easy to pair with a range of outfits, and have Ultra Go cushioning to keep you light on your feet. Make sure to add a pair to your basket! <a class="view-deal button" href="https://www.amazon.com/Skechers-Mens-Walk-Flex-Hands-Sneaker/dp/B0CFN8VR99" target="_blank" rel="nofollow" data-dimension112="5a29d5be-cba6-11f1-bd2f-798e978702b7" data-action="Deal Block" data-label="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension48="Slip-Ins Go Walk Flex Hands Up Sneaker" data-dimension25="$57">View Deal</a></p></div><h3 class="article-body__section" id="section-birkenstocks"><span>Birkenstocks</span></h3><div class="product"><a data-dimension112="5a29d690-cba6-11f1-849e-47b50a3b8654" data-action="Deal Block" data-label="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension48="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension25="$30" href="https://www.nordstromrack.com/s/birkenstock-arizona-stealth-buckle-eva-slide-sandal-women/7945865?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1560px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="3Qt2UrH7ESWm55JQpi8aXQ" name="Arizona Stealth" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3Qt2UrH7ESWm55JQpi8aXQ-1920-80.jpg" mos="" align="middle" fullscreen="" width="1560" height="2340" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nordstromrack.com/s/birkenstock-arizona-stealth-buckle-eva-slide-sandal-women/7945865?" target="_blank" rel="nofollow" data-dimension112="5a29d690-cba6-11f1-849e-47b50a3b8654" data-action="Deal Block" data-label="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension48="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension25="$30">Arizona Stealth Buckle EVA Slide (Women's): was $54 now $30</a></strong><br />A pair of Birkenstocks for $30??? Sign me up. Fall might be here, but warm weather is still hanging around. These waterproof slides are perfect for the beach and pool. They feature a rubber-like texture with sleek adjustable straps and a grippy traction sole. <a class="view-deal button" href="https://www.nordstromrack.com/s/birkenstock-arizona-stealth-buckle-eva-slide-sandal-women/7945865?" target="_blank" rel="nofollow" data-dimension112="5a29d690-cba6-11f1-849e-47b50a3b8654" data-action="Deal Block" data-label="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension48="Arizona Stealth Buckle EVA Slide (Women's)" data-dimension25="$30">View Deal</a></p></div><div class="product"><a data-dimension112="5a29d6f4-cba6-11f1-91b0-a1cf04b003e0" data-action="Deal Block" data-label="Madrid Eva Big Buckle (Women's)" data-dimension48="Madrid Eva Big Buckle (Women's)" data-dimension25="$54" href="https://www.amazon.com/Birkenstock-Womens-Madrid-Buckle-11-11-5/dp/B0FH16M2GN" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:41.58%;"><img id="hnaAiVGGAv8vC6hXNTjrfG" name="Madrid Eva Big Buckle (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/hnaAiVGGAv8vC6hXNTjrfG-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="289" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Birkenstock-Womens-Madrid-Buckle-11-11-5/dp/B0FH16M2GN" target="_blank" rel="nofollow" data-dimension112="5a29d6f4-cba6-11f1-91b0-a1cf04b003e0" data-action="Deal Block" data-label="Madrid Eva Big Buckle (Women's)" data-dimension48="Madrid Eva Big Buckle (Women's)" data-dimension25="$54">Madrid Eva Big Buckle (Women's): was $66 now $54</a></strong><br />The classic Birkenstock look, without the leather. These EVA big buckle sandels come in a cool Gray Taupe color and are water-friendly, too.<a class="view-deal button" href="https://www.amazon.com/Birkenstock-Womens-Madrid-Buckle-11-11-5/dp/B0FH16M2GN" target="_blank" rel="nofollow" data-dimension112="5a29d6f4-cba6-11f1-91b0-a1cf04b003e0" data-action="Deal Block" data-label="Madrid Eva Big Buckle (Women's)" data-dimension48="Madrid Eva Big Buckle (Women's)" data-dimension25="$54">View Deal</a></p></div><div class="product"><a data-dimension112="5a29d762-cba6-11f1-85fb-556c01a4ea44" data-action="Deal Block" data-label="Papilio Florida Platform Flex (Women's)" data-dimension48="Papilio Florida Platform Flex (Women's)" data-dimension25="$74" href="https://www.nordstromrack.com/s/florida-flex-platform-slide-sandal-women/7953334?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1560px;"><p class="vanilla-image-block" style="padding-top:150.00%;"><img id="YToScW8bDWGEAAJqToJey" name="florida" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/YToScW8bDWGEAAJqToJey-1920-80.jpg" mos="" align="middle" fullscreen="" width="1560" height="2340" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.nordstromrack.com/s/florida-flex-platform-slide-sandal-women/7953334?" target="_blank" rel="nofollow" data-dimension112="5a29d762-cba6-11f1-85fb-556c01a4ea44" data-action="Deal Block" data-label="Papilio Florida Platform Flex (Women's)" data-dimension48="Papilio Florida Platform Flex (Women's)" data-dimension25="$74">Papilio Florida Platform Flex (Women's): was $144 now $74</a></strong><br />These Papilio by Birkenstock sandals feature a platform and three straps for extra support. Reviewers love their iconic design and comfortable, adjustable fit.<a class="view-deal button" href="https://www.nordstromrack.com/s/florida-flex-platform-slide-sandal-women/7953334?" target="_blank" rel="nofollow" data-dimension112="5a29d762-cba6-11f1-85fb-556c01a4ea44" data-action="Deal Block" data-label="Papilio Florida Platform Flex (Women's)" data-dimension48="Papilio Florida Platform Flex (Women's)" data-dimension25="$74">View Deal</a></p></div><div class="product"><a data-dimension112="b57f11e4-cc6a-11f1-873c-53c4512c2a48" data-action="Deal Block" data-label="Mayari - Printed Footbed Sandal (Women's)" data-dimension48="Mayari - Printed Footbed Sandal (Women's)" data-dimension25="$90" href="https://www.amazon.com/Birkenstock-Womens-Mayari-Printed-Footbed-Sandal/dp/B0FH1FHW6F" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:46.47%;"><img id="puE7T2AENpTehS3ncU69oY" name="Mayari - Printed Footbed Sandal (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/puE7T2AENpTehS3ncU69oY-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="323" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Birkenstock-Womens-Mayari-Printed-Footbed-Sandal/dp/B0FH1FHW6F" target="_blank" rel="nofollow" data-dimension112="b57f11e4-cc6a-11f1-873c-53c4512c2a48" data-action="Deal Block" data-label="Mayari - Printed Footbed Sandal (Women's)" data-dimension48="Mayari - Printed Footbed Sandal (Women's)" data-dimension25="$90">Mayari - Printed Footbed Sandal (Women's): was $112 now $90</a></strong><br />As well as a soft Pure Sage strap, these Birkenstock sandals have a beautiful floral design printed on the footbed. The double straps and toe loop keep them securely on your feet.<a class="view-deal button" href="https://www.amazon.com/Birkenstock-Womens-Mayari-Printed-Footbed-Sandal/dp/B0FH1FHW6F" target="_blank" rel="nofollow" data-dimension112="b57f11e4-cc6a-11f1-873c-53c4512c2a48" data-action="Deal Block" data-label="Mayari - Printed Footbed Sandal (Women's)" data-dimension48="Mayari - Printed Footbed Sandal (Women's)" data-dimension25="$90">View Deal</a></p></div><h3 class="article-body__section" id="section-cushionaire"><span>Cushionaire</span></h3><div class="product"><a data-dimension112="4a99259e-cdfb-11f1-9750-511e1be1b23c" data-action="Deal Block" data-label="Java Casual Jelly Flats (Women's)" data-dimension48="Java Casual Jelly Flats (Women's)" data-dimension25="$34" href="https://www.amazon.com/dp/B0H4MLLC32" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:514px;"><p class="vanilla-image-block" style="padding-top:135.21%;"><img id="fA5iQ9SRNPyHw3htEEeMiK" name="Java Casual Jelly Flats (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/fA5iQ9SRNPyHw3htEEeMiK-1920-80.jpg" mos="" align="middle" fullscreen="" width="514" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0H4MLLC32" target="_blank" rel="nofollow" data-dimension112="4a99259e-cdfb-11f1-9750-511e1be1b23c" data-action="Deal Block" data-label="Java Casual Jelly Flats (Women's)" data-dimension48="Java Casual Jelly Flats (Women's)" data-dimension25="$34">Java Casual Jelly Flats (Women's): was $49 now $34</a></strong><br />These jelly flats from Cushionaire are flexible, easy to slip on and stay put thanks to a buckle. They feature a water-friendly construction that wipes clean with ease and also makes them practical pool shoes for vacations, errands and busy days. <a class="view-deal button" href="https://www.amazon.com/dp/B0H4MLLC32" target="_blank" rel="nofollow" data-dimension112="4a99259e-cdfb-11f1-9750-511e1be1b23c" data-action="Deal Block" data-label="Java Casual Jelly Flats (Women's)" data-dimension48="Java Casual Jelly Flats (Women's)" data-dimension25="$34">View Deal</a></p></div><div class="product"><a data-dimension112="4a992634-cdfb-11f1-95b6-d1b60e3eb69b" data-action="Deal Block" data-label="Talisa Espadrilles for Women" data-dimension48="Talisa Espadrilles for Women" data-dimension25="$37" href="https://www.amazon.com/dp/B0GXGRQDNQ?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:581px;"><p class="vanilla-image-block" style="padding-top:119.62%;"><img id="UxL9TT6inJkWtC3et4tVLX" name="Talisa" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/UxL9TT6inJkWtC3et4tVLX-1920-80.jpg" mos="" align="middle" fullscreen="" width="581" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0GXGRQDNQ?" target="_blank" rel="nofollow" data-dimension112="4a992634-cdfb-11f1-95b6-d1b60e3eb69b" data-action="Deal Block" data-label="Talisa Espadrilles for Women" data-dimension48="Talisa Espadrilles for Women" data-dimension25="$37">Talisa Espadrilles for Women: was $64 now $37</a></strong><br />If you're looking for a closed-toe shoe that's a bit elevated, these espadrilles are the way to go. They have crossover elastic straps that hug your ankle for a secure fit and they stretch as you move. They also have a slight wedge that's still comfortable enough to walk on. <a class="view-deal button" href="https://www.amazon.com/dp/B0GXGRQDNQ?" target="_blank" rel="nofollow" data-dimension112="4a992634-cdfb-11f1-95b6-d1b60e3eb69b" data-action="Deal Block" data-label="Talisa Espadrilles for Women" data-dimension48="Talisa Espadrilles for Women" data-dimension25="$37">View Deal</a></p></div><div class="product"><a data-dimension112="5a29d898-cba6-11f1-934d-13d0e2030136" data-action="Deal Block" data-label="Laz Cork Footbed Sandals" data-dimension48="Laz Cork Footbed Sandals" data-dimension25="$39" href="https://www.amazon.com/dp/B0H8FB19F7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:606px;"><p class="vanilla-image-block" style="padding-top:114.69%;"><img id="GknzxZr7RhbEEsFqQG3HjN" name="Laz" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/GknzxZr7RhbEEsFqQG3HjN-1920-80.jpg" mos="" align="middle" fullscreen="" width="606" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0H8FB19F7" target="_blank" rel="nofollow" data-dimension112="5a29d898-cba6-11f1-934d-13d0e2030136" data-action="Deal Block" data-label="Laz Cork Footbed Sandals" data-dimension48="Laz Cork Footbed Sandals" data-dimension25="$39">Laz Cork Footbed Sandals: was $59 now $39</a></strong><br />If you're in the market for some Birkenstocks but don't want to pay the hefty price, these Cushionaire sandals are the next best thing. Crafted from high-quality faux leather, the sandals feature a soft lining and adjustable double buckle strap. They're also available in a plethora of colors, although price may vary. <a class="view-deal button" href="https://www.amazon.com/dp/B0H8FB19F7" target="_blank" rel="nofollow" data-dimension112="5a29d898-cba6-11f1-934d-13d0e2030136" data-action="Deal Block" data-label="Laz Cork Footbed Sandals" data-dimension48="Laz Cork Footbed Sandals" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="5a29d8fc-cba6-11f1-893c-4df15183fb6f" data-action="Deal Block" data-label="Lens Sandals" data-dimension48="Lens Sandals" data-dimension25="$49" href="https://www.amazon.com/dp/B0GZJ8VB6M" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:543px;"><p class="vanilla-image-block" style="padding-top:127.99%;"><img id="v9a622fikJvyBJaGFHRcpH" name="Cushionaire Lens" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/v9a622fikJvyBJaGFHRcpH-1920-80.jpg" mos="" align="middle" fullscreen="" width="543" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0GZJ8VB6M" target="_blank" rel="nofollow" data-dimension112="5a29d8fc-cba6-11f1-893c-4df15183fb6f" data-action="Deal Block" data-label="Lens Sandals" data-dimension48="Lens Sandals" data-dimension25="$49">Lens Sandals: was $69 now $49</a></strong><br />Looking for a fun little twist on a classic slide? Slip into these comfortable sandals that feature unique braided straps. They have a cushioned footbed and a contoured sole making them extra comfy. They also pair nicely with dresses, denim and casual outfits.<a class="view-deal button" href="https://www.amazon.com/dp/B0GZJ8VB6M" target="_blank" rel="nofollow" data-dimension112="5a29d8fc-cba6-11f1-893c-4df15183fb6f" data-action="Deal Block" data-label="Lens Sandals" data-dimension48="Lens Sandals" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="5a29d9c4-cba6-11f1-bc65-41b830e20f20" data-action="Deal Block" data-label="Missy Mary Jane Ballet Flats" data-dimension48="Missy Mary Jane Ballet Flats" data-dimension25="$49" href="https://www.amazon.com/dp/B0GYXT459Z?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:534px;"><p class="vanilla-image-block" style="padding-top:130.15%;"><img id="ZXhLhPRFgdWuUD2Keq2vQj" name="Cushionaire mary jane" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZXhLhPRFgdWuUD2Keq2vQj-1920-80.jpg" mos="" align="middle" fullscreen="" width="534" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0GYXT459Z?" target="_blank" rel="nofollow" data-dimension112="5a29d9c4-cba6-11f1-bc65-41b830e20f20" data-action="Deal Block" data-label="Missy Mary Jane Ballet Flats" data-dimension48="Missy Mary Jane Ballet Flats" data-dimension25="$49">Missy Mary Jane Ballet Flats: was $69 now $49</a></strong><br />Classic Mary Janes meet sophisticated ballet flats in this shoe that is lightweight, soft and flexible. They're great for everyday wear and even though they feature a velvet material, they are breathable. <a class="view-deal button" href="https://www.amazon.com/dp/B0GYXT459Z?" target="_blank" rel="nofollow" data-dimension112="5a29d9c4-cba6-11f1-bc65-41b830e20f20" data-action="Deal Block" data-label="Missy Mary Jane Ballet Flats" data-dimension48="Missy Mary Jane Ballet Flats" data-dimension25="$49">View Deal</a></p></div><h3 class="article-body__section" id="section-new-balance"><span>New Balance</span></h3><div class="product"><a data-dimension112="5a29da96-cba6-11f1-b25d-7f9ebe944c8c" data-action="Deal Block" data-label="515 Sneaker (Women's)" data-dimension48="515 Sneaker (Women's)" data-dimension25="$55" href="https://www.amazon.com/New-Balance-Sneaker-Reflection-Aluminum/dp/B09YBLCL41" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:747px;"><p class="vanilla-image-block" style="padding-top:57.30%;"><img id="twUFoFTRbcG9RAJR2CTDER" name="515 Sneaker (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/twUFoFTRbcG9RAJR2CTDER-1920-80.jpg" mos="" align="middle" fullscreen="" width="747" height="428" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-Sneaker-Reflection-Aluminum/dp/B09YBLCL41" target="_blank" rel="nofollow" data-dimension112="5a29da96-cba6-11f1-b25d-7f9ebe944c8c" data-action="Deal Block" data-label="515 Sneaker (Women's)" data-dimension48="515 Sneaker (Women's)" data-dimension25="$55">515 Sneaker (Women's): was $79 now $55</a></strong><br />Featuring an understated style in a wide selection of colors, the New Balance 515 sneakers are a wardrobe staple. The upper is made of a mix of suede and mesh, and the soles provide all-day comfort.<a class="view-deal button" href="https://www.amazon.com/New-Balance-Sneaker-Reflection-Aluminum/dp/B09YBLCL41" target="_blank" rel="nofollow" data-dimension112="5a29da96-cba6-11f1-b25d-7f9ebe944c8c" data-action="Deal Block" data-label="515 Sneaker (Women's)" data-dimension48="515 Sneaker (Women's)" data-dimension25="$55">View Deal</a></p></div><div class="product"><a data-dimension112="5a29db04-cba6-11f1-b343-9367060aa4f8" data-action="Deal Block" data-label="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension48="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension25="$98" href="https://www.amazon.com/New-Balance-FuelCell-Walking-Electric/dp/B0D2Y7L3DC" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:755px;"><p class="vanilla-image-block" style="padding-top:55.23%;"><img id="ufsfox6NerPUoEY6YYZYXk" name="FuelCell Walker Elite V1 Walking Shoe (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ufsfox6NerPUoEY6YYZYXk-1920-80.jpg" mos="" align="middle" fullscreen="" width="755" height="417" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-FuelCell-Walking-Electric/dp/B0D2Y7L3DC" target="_blank" rel="nofollow" data-dimension112="5a29db04-cba6-11f1-b343-9367060aa4f8" data-action="Deal Block" data-label="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension48="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension25="$98">FuelCell Walker Elite V1 Walking Shoe (Women's): was $139 now $98</a></strong><br />Engineered for walking, the New Balance FuelCell Walker Elite V1 Walking Shoes are cushioned, stable, and propel your feet forward with each step. They look super sleek, too. <a class="view-deal button" href="https://www.amazon.com/New-Balance-FuelCell-Walking-Electric/dp/B0D2Y7L3DC" target="_blank" rel="nofollow" data-dimension112="5a29db04-cba6-11f1-b343-9367060aa4f8" data-action="Deal Block" data-label="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension48="FuelCell Walker Elite V1 Walking Shoe (Women's)" data-dimension25="$98">View Deal</a></p></div><h3 class="article-body__section" id="section-dr-martens"><span>Dr Martens</span></h3><div class="product"><a data-dimension112="6efccfcc-cba7-11f1-ac8b-4364d76bdba0" data-action="Deal Block" data-label="Sanguine Leather Chelsea Boot (Women's)" data-dimension48="Sanguine Leather Chelsea Boot (Women's)" data-dimension25="$119" href="https://www.amazon.com/Dr-Martens-Sanguine-Leather-Chelsea/dp/B0FFGHQ3L4" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:622px;"><p class="vanilla-image-block" style="padding-top:111.74%;"><img id="jBsVYKGReMs9YKKMZkCkBC" name="Sanguine Leather Chelsea Boot (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jBsVYKGReMs9YKKMZkCkBC-1920-80.jpg" mos="" align="middle" fullscreen="" width="622" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Dr-Martens-Sanguine-Leather-Chelsea/dp/B0FFGHQ3L4" target="_blank" rel="nofollow" data-dimension112="6efccfcc-cba7-11f1-ac8b-4364d76bdba0" data-action="Deal Block" data-label="Sanguine Leather Chelsea Boot (Women's)" data-dimension48="Sanguine Leather Chelsea Boot (Women's)" data-dimension25="$119">Sanguine Leather Chelsea Boot (Women's): was $135 now $119</a></strong><br />Nothing screams "fall" more than a Chelsea boot. Coming from Dr Martens, this pair is extra-durable and has a water resistant coating. Not only does the pull tab make them stand out — it makes them easier to put on!<a class="view-deal button" href="https://www.amazon.com/Dr-Martens-Sanguine-Leather-Chelsea/dp/B0FFGHQ3L4" target="_blank" rel="nofollow" data-dimension112="6efccfcc-cba7-11f1-ac8b-4364d76bdba0" data-action="Deal Block" data-label="Sanguine Leather Chelsea Boot (Women's)" data-dimension48="Sanguine Leather Chelsea Boot (Women's)" data-dimension25="$119">View Deal</a></p></div><div class="product"><a data-dimension112="6efcd03a-cba7-11f1-ace3-ad0127b6787f" data-action="Deal Block" data-label="1460 8 Eye Boot (Unisex)" data-dimension48="1460 8 Eye Boot (Unisex)" data-dimension25="$153" href="https://www.amazon.com/Dr-Martens-Smooth-Combat-Womens/dp/B004SI1QNU/" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:684px;"><p class="vanilla-image-block" style="padding-top:101.61%;"><img id="imnJnaGkotNWgHnjsGETSk" name="1460 8 Eye Boot" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/imnJnaGkotNWgHnjsGETSk-1920-80.jpg" mos="" align="middle" fullscreen="" width="684" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Dr-Martens-Smooth-Combat-Womens/dp/B004SI1QNU/" target="_blank" rel="nofollow" data-dimension112="6efcd03a-cba7-11f1-ace3-ad0127b6787f" data-action="Deal Block" data-label="1460 8 Eye Boot (Unisex)" data-dimension48="1460 8 Eye Boot (Unisex)" data-dimension25="$153">1460 8 Eye Boot (Unisex): was $180 now $153</a></strong><br />Right now Dr. Martens’ 1460 8 Eye Boots have seen a discount at Amazon. Made of vegan leather, their slip-resistant soles and tough construction make them great for both work and everyday wear.<a class="view-deal button" href="https://www.amazon.com/Dr-Martens-Smooth-Combat-Womens/dp/B004SI1QNU/" target="_blank" rel="nofollow" data-dimension112="6efcd03a-cba7-11f1-ace3-ad0127b6787f" data-action="Deal Block" data-label="1460 8 Eye Boot (Unisex)" data-dimension48="1460 8 Eye Boot (Unisex)" data-dimension25="$153">View Deal</a></p></div><h3 class="article-body__section" id="section-timberland"><span>Timberland</span></h3><div class="product"><a data-dimension112="49e34d5a-cba8-11f1-b931-cdf54df1eceb" data-action="Deal Block" data-label="Davis Square Chukka Shoe (Men's)" data-dimension48="Davis Square Chukka Shoe (Men's)" data-dimension25="$48" href="https://www.amazon.com/Timberland-Davis-Square-Chukka-Wheat/dp/B0D54GMPLS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:895px;"><p class="vanilla-image-block" style="padding-top:77.65%;"><img id="9sA8mqcAuQkkDAVnQjVBqj" name="Davis Square Chukka Shoe (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/9sA8mqcAuQkkDAVnQjVBqj-1920-80.jpg" mos="" align="middle" fullscreen="" width="895" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Timberland-Davis-Square-Chukka-Wheat/dp/B0D54GMPLS" target="_blank" rel="nofollow" data-dimension112="49e34d5a-cba8-11f1-b931-cdf54df1eceb" data-action="Deal Block" data-label="Davis Square Chukka Shoe (Men's)" data-dimension48="Davis Square Chukka Shoe (Men's)" data-dimension25="$48">Davis Square Chukka Shoe (Men's): was $95 now $48</a></strong><br />Classic, stylish and comfortable. It doesn't get better than the Davis Square Chukka Shoe — especially when you can get a pair for almost half off. These are made of premium Timberland leather and have comfortable OrthoLite insoles.<a class="view-deal button" href="https://www.amazon.com/Timberland-Davis-Square-Chukka-Wheat/dp/B0D54GMPLS" target="_blank" rel="nofollow" data-dimension112="49e34d5a-cba8-11f1-b931-cdf54df1eceb" data-action="Deal Block" data-label="Davis Square Chukka Shoe (Men's)" data-dimension48="Davis Square Chukka Shoe (Men's)" data-dimension25="$48">View Deal</a></p></div><div class="product"><a data-dimension112="49e34dd2-cba8-11f1-9bca-6150122cd4a8" data-action="Deal Block" data-label="Linden Woods 6-Inch Waterproof Boot (Women's)" data-dimension48="Linden Woods 6-Inch Waterproof Boot (Women's)" data-dimension25="$111" href="https://www.amazon.com/Timberland-Womens-Waterproof-Fashion-Black-New/dp/B0D47QK4VT" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:605px;"><p class="vanilla-image-block" style="padding-top:114.88%;"><img id="mW6fWKfX39uKuvWZUuMbnA" name="Linden Woods 6-Inch Waterproof Boot (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/mW6fWKfX39uKuvWZUuMbnA-1920-80.jpg" mos="" align="middle" fullscreen="" width="605" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Timberland-Womens-Waterproof-Fashion-Black-New/dp/B0D47QK4VT" target="_blank" rel="nofollow" data-dimension112="49e34dd2-cba8-11f1-9bca-6150122cd4a8" data-action="Deal Block" data-label="Linden Woods 6-Inch Waterproof Boot (Women's)" data-dimension48="Linden Woods 6-Inch Waterproof Boot (Women's)" data-dimension25="$111">Linden Woods 6-Inch Waterproof Boot (Women's): was $140 now $111</a></strong><br />These ankle boots offer versatility, function — and protection for the elements. Not only are they stylish, but they also have rubber lug outsoles for excellent traction and grip on slippery surfaces. <a class="view-deal button" href="https://www.amazon.com/Timberland-Womens-Waterproof-Fashion-Black-New/dp/B0D47QK4VT" target="_blank" rel="nofollow" data-dimension112="49e34dd2-cba8-11f1-9bca-6150122cd4a8" data-action="Deal Block" data-label="Linden Woods 6-Inch Waterproof Boot (Women's)" data-dimension48="Linden Woods 6-Inch Waterproof Boot (Women's)" data-dimension25="$111">View Deal</a></p></div><h3 class="article-body__section" id="section-asics"><span>Asics</span></h3><div class="product"><a data-dimension112="5a29dbd6-cba6-11f1-98f1-1d2e557f423c" data-action="Deal Block" data-label="Tiger Runner II (Women's)" data-dimension48="Tiger Runner II (Women's)" data-dimension25="$59" href="https://www.amazon.com/ASICS-Womens-Runner-Sportstyle-Silver/dp/B0H3F1WSB3" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:682px;"><p class="vanilla-image-block" style="padding-top:75.07%;"><img id="vcT4ZrTkbB5kx6uGRWjquJ" name="asics tiger runner ii" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vcT4ZrTkbB5kx6uGRWjquJ-1920-80.png" mos="" align="middle" fullscreen="" width="682" height="512" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Runner-Sportstyle-Silver/dp/B0H3F1WSB3" target="_blank" rel="nofollow" data-dimension112="5a29dbd6-cba6-11f1-98f1-1d2e557f423c" data-action="Deal Block" data-label="Tiger Runner II (Women's)" data-dimension48="Tiger Runner II (Women's)" data-dimension25="$59">Tiger Runner II (Women's): was $85 now $59</a></strong><br />Designed for everyday wear, these Asics sneakers are inspired by classic 80s jogging shoes. On the inside, they're packed with today's best cushioning and durability.<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Runner-Sportstyle-Silver/dp/B0H3F1WSB3" target="_blank" rel="nofollow" data-dimension112="5a29dbd6-cba6-11f1-98f1-1d2e557f423c" data-action="Deal Block" data-label="Tiger Runner II (Women's)" data-dimension48="Tiger Runner II (Women's)" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="5a29dc3a-cba6-11f1-a90c-53047959208b" data-action="Deal Block" data-label="Gel-Venture 11" data-dimension48="Gel-Venture 11" data-dimension25="$69" href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Carrier/dp/B0FV72G49S" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1146px;"><p class="vanilla-image-block" style="padding-top:75.04%;"><img id="44i7uWA8WvTqRemkvKZpV6" name="Gel-Venture 11" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/44i7uWA8WvTqRemkvKZpV6-1920-80.jpg" mos="" align="middle" fullscreen="" width="1146" height="860" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Asics Gel-Venture 11 are designed for everyday runs and walks! They have Amplifoam Plus midsole cushioning on board, and a 2mm higher stack height — 2mm of extra softness to absorb impact and keep you comfortable for hours.<a class="view-deal button" href="https://www.amazon.com/ASICS-Gel-Venture-Running-Shoes-Carrier/dp/B0FV72G49S" target="_blank" rel="nofollow" data-dimension112="5a29dc3a-cba6-11f1-a90c-53047959208b" data-action="Deal Block" data-label="Gel-Venture 11" data-dimension48="Gel-Venture 11" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="5a29dc9e-cba6-11f1-95a5-ff83973278af" data-action="Deal Block" data-label="Gel-K1011 Sneakers (Men's)" data-dimension48="Gel-K1011 Sneakers (Men's)" data-dimension25="$99" href="https://www.asics.com/us/en-us/gel-k1011/p/ANA_1203A830-003.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:683px;"><p class="vanilla-image-block" style="padding-top:74.96%;"><img id="iyit4YAmvDQPwsHoyfwz4f" name="Gel-K1011 Shoes" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/iyit4YAmvDQPwsHoyfwz4f-1920-80.webp" mos="" align="middle" fullscreen="" width="683" height="512" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.asics.com/us/en-us/gel-k1011/p/ANA_1203A830-003.html" target="_blank" rel="nofollow" data-dimension112="5a29dc9e-cba6-11f1-95a5-ff83973278af" data-action="Deal Block" data-label="Gel-K1011 Sneakers (Men's)" data-dimension48="Gel-K1011 Sneakers (Men's)" data-dimension25="$99">Gel-K1011 Sneakers (Men's): was $140 now $99</a></strong><br />An iconic design and reliable comfort, what more could you want from a pair of sneakers? It takes cues from some of Asics' best shoes, with Gel-Kayano-inspired panels on the upper and the same midsole tooling system as the Gel-Cumulus 17.<a class="view-deal button" href="https://www.asics.com/us/en-us/gel-k1011/p/ANA_1203A830-003.html" target="_blank" rel="nofollow" data-dimension112="5a29dc9e-cba6-11f1-95a5-ff83973278af" data-action="Deal Block" data-label="Gel-K1011 Sneakers (Men's)" data-dimension48="Gel-K1011 Sneakers (Men's)" data-dimension25="$99">View Deal</a></p></div><h3 class="article-body__section" id="section-hoka"><span>Hoka</span></h3><div class="product"><a data-dimension112="5a29dd66-cba6-11f1-96f7-77a3c98b8bcd" data-action="Deal Block" data-label="Skyflow (Men's)" data-dimension48="Skyflow (Men's)" data-dimension25="$112" href="https://www.hoka.com/en/us/mens-everyday-running-shoes/skyflow/1155111.html?dwvar_1155111_color=SRYS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1932px;"><p class="vanilla-image-block" style="padding-top:81.11%;"><img id="WvCZL3SYYevA9hGSrJNCDD" name="Hoka skyflow" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/WvCZL3SYYevA9hGSrJNCDD-1920-80.jpg" mos="" align="middle" fullscreen="" width="1932" height="1567" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/mens-everyday-running-shoes/skyflow/1155111.html?dwvar_1155111_color=SRYS" target="_blank" rel="nofollow" data-dimension112="5a29dd66-cba6-11f1-96f7-77a3c98b8bcd" data-action="Deal Block" data-label="Skyflow (Men's)" data-dimension48="Skyflow (Men's)" data-dimension25="$112">Skyflow (Men's): was $160 now $112</a></strong><br />The Hoka Skyflow is a comfortable, cushioned running shoe with a midsole made from a lightweight supercritical EVA foam. It's a protective shoe that's also quite versatile, and a good option for walking and runners of all levels.<a class="view-deal button" href="https://www.hoka.com/en/us/mens-everyday-running-shoes/skyflow/1155111.html?dwvar_1155111_color=SRYS" target="_blank" rel="nofollow" data-dimension112="5a29dd66-cba6-11f1-96f7-77a3c98b8bcd" data-action="Deal Block" data-label="Skyflow (Men's)" data-dimension48="Skyflow (Men's)" data-dimension25="$112">View Deal</a></p></div><div class="product"><a data-dimension112="5a29ddd4-cba6-11f1-99c5-e724d8a99ce9" data-action="Deal Block" data-label="Clifton 10 (Men's)" data-dimension48="Clifton 10 (Men's)" data-dimension25="$124" href="https://www.hoka.com/en/us/mens-everyday-running-gear/clifton-10/1162030.html" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2220px;"><p class="vanilla-image-block" style="padding-top:81.13%;"><img id="MKZ2WmvKiUZp3LodsbSF47" name="Hoka Clifton 10" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/MKZ2WmvKiUZp3LodsbSF47-1920-80.png" mos="" align="middle" fullscreen="" width="2220" height="1801" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/mens-everyday-running-gear/clifton-10/1162030.html" target="_blank" rel="nofollow" data-dimension112="5a29ddd4-cba6-11f1-99c5-e724d8a99ce9" data-action="Deal Block" data-label="Clifton 10 (Men's)" data-dimension48="Clifton 10 (Men's)" data-dimension25="$124">Clifton 10 (Men's): was $155 now $124</a></strong><br />The <a href="https://www.tomsguide.com/wellness/running/ive-tested-nearly-every-hoka-running-shoe-these-are-my-3-top-picks">Hoka Clifton 10</a> is one of the most popular running shoes from any brand, and a top option for newer runners in particular. It's comfortable, but pretty lightweight, and enjoyable for easy and fast training runs. This is another shoe that's not due for a big update in 2026, so don't wait for the Clifton 11; bag this deal instead.<a class="view-deal button" href="https://www.hoka.com/en/us/mens-everyday-running-gear/clifton-10/1162030.html" target="_blank" rel="nofollow" data-dimension112="5a29ddd4-cba6-11f1-99c5-e724d8a99ce9" data-action="Deal Block" data-label="Clifton 10 (Men's)" data-dimension48="Clifton 10 (Men's)" data-dimension25="$124">View Deal</a></p></div><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Home+Appliances&amp;view_mode=savings_squad&amp;widget_title=Top+Deals+Handpicked+by+Our+Editors&amp;widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&amp;bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                if (externalUrl) {                   if (seenUrls.has(externalUrl)) return;                  seenUrls.add(externalUrl);                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || '',                   authorName: article.articleauthortext ? article.articleauthortext[0] : (article.articleauthor ? article.articleauthor[0] : ''),                   authorRole: article.articleauthorrole ? article.articleauthorrole[0] : '',                   authorImage: article.articleauthormedia ? article.articleauthormedia[0] : '',                   documentUrl: article.documenturl ? article.documenturl[0] : '',                   modifiedDate: article.contentmodifieddate || article.modifieddate || ''                });             });          });                    const airedaleBrandsList = Object.keys(overallBrandsCounts).map(b => ({              formatted_value: b,              count: overallBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I ran hundreds of miles with 5 pairs of prescription sports sunglasses — these are the best ones to buy ]]></title>
                                                                                                <dc:content><![CDATA[ <p>If you’re short- or long-sighted, active and have never invested in a set of prescription sports sunglasses or glasses, I’m here to tell you that it’s a game-changer.</p><p>I’ve been running more or less daily for over 10 years and only really caught on to prescription sports sunnies in the last five years, and they make each and every workout more enjoyable.</p><p>In the distant past, I just used my regular glasses, which slipped down my nose, bounced and didn’t work with doses of heavy sweating. </p><p>Of course I’ve also tried contact lenses, but they’re a hassle and an expensive option just to use for runs, since I don’t find them comfortable to wear all day.</p><p>I’ve now tested a lot of different prescription sports sunglasses, and I’ve covered the pros and cons of five of my favorite sets below after running hundreds of miles with them as well as cycling.</p><h3 class="article-body__section" id="section-zenni-optical-zunnies-wrap-around-sports-sunglasses"><span>Zenni Optical Zunnies Wrap-Around Sports Sunglasses</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:2189px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="KsngQTMvES2JHeWPfetw4G" name="Zenni Optical Zunnies Wrap-Around Sunglasses" alt="Zenni Optical Zunnies Wrap-Around Sunglasses" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:111,l:180,cw:2189,ch:1231,q:80/KsngQTMvES2JHeWPfetw4G.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>I have three pairs of these sunglasses, the last of which I bought just to get them in a color I prefer for races, which gives you some indication of how much I like them.</p><p>Zenni’s Zunnies line-up contains some of the best value prescription sports sunglasses and glasses I’ve come across, and these lightweight wraparound sunnies hit all the key markers I look for.</p><p>The fit is perfect, with the sunglasses staying firmly in place over runs of any length (including marathons in my testing) without any pressure points.</p><p>There’s a variety of lens styles and tints to pick from, and you can choose standard or wider lenses to suit your face. Whatever combo you opt for, the price stays south of $150, and many sets will cost you less than $100. For most people, these would be my top pick.</p><div class="product"><a data-dimension112="be5e88ee-c8aa-11f1-b619-c5611a5ee28b" data-action="Deal Block" data-label="Zunnies Wrap-Around Sunglasses" data-dimension48="Zunnies Wrap-Around Sunglasses" data-dimension25="$23.95" href="https://www.zennioptical.com/p/halfrim-plastic-wrap-around-sunglass-frames/10134/1013421" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1200px;"><p class="vanilla-image-block" style="padding-top:31.17%;"><img id="QzGZbGXZ9qawtm89ngyFtS" name="Zenni Optical Zunnies Wrap-Around Sunglasses" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/QzGZbGXZ9qawtm89ngyFtS-1920-80.png" mos="" align="middle" fullscreen="" width="1200" height="374" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.zennioptical.com/p/halfrim-plastic-wrap-around-sunglass-frames/10134/1013421" target="_blank" rel="nofollow" data-dimension112="be5e88ee-c8aa-11f1-b619-c5611a5ee28b" data-action="Deal Block" data-label="Zunnies Wrap-Around Sunglasses" data-dimension48="Zunnies Wrap-Around Sunglasses" data-dimension25="$23.95">Zunnies Wrap-Around Sunglasses: $23.95</a></strong><br />These Zenni Zunnies are my prescription running sunglasses overall, partly thanks to the great value they offer. Even with prescription lenses, you'll probably only have to pay around $80-$130, depending on the lenses you opt for.<a class="view-deal button" href="https://www.zennioptical.com/p/halfrim-plastic-wrap-around-sunglass-frames/10134/1013421" target="_blank" rel="nofollow" data-dimension112="be5e88ee-c8aa-11f1-b619-c5611a5ee28b" data-action="Deal Block" data-label="Zunnies Wrap-Around Sunglasses" data-dimension48="Zunnies Wrap-Around Sunglasses" data-dimension25="$23.95">View Deal</a></p></div><h3 class="article-body__section" id="section-ombraz-teton"><span>Ombraz Teton</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:3972px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="YnFyULgnuQBKYe2VJonf69" name="Ombraz Teton Sunglasses" alt="Ombraz Teton Sunglasses" src="https://cdn.mos.cms.futurecdn.net/YnFyULgnuQBKYe2VJonf69-1920-80.jpg" mos="" align="middle" fullscreen="" width="3972" height="2234" 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>Ombraz’s line-up of sunglasses uses a cord instead of arms, and this is a brilliantly simple and effective way to get a guaranteed great fit for sports.</p><p>I’ve used the Teton regularly throughout my current marathon training block, and I have them with photochromic lenses so I can actually wear them for indoor runs, bike rides and night runs.</p><p>The fit is quick and easy to adjust, and you don’t have to tighten the cord so much that it puts any pressure on your head to ensure the Teton sunnies stay in place.</p><p>They’re also stylish sunglasses for general use, and because they don’t have arms, they pack away in a flat case, so they’re easy to take on trips.</p><p>The price for the prescription version of the sunglasses is high, though, several times what you pay for the standard Ombraz Teton with normal lenses.</p><div class="product"><a data-dimension112="943f142e-c8ab-11f1-b94c-098273589a7a" data-action="Deal Block" data-label="Teton (prescription)" data-dimension48="Teton (prescription)" data-dimension25="$470" href="https://lensandframe.co/products/ombraz-teton-prescription-eyeglasses-tortoise?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:66.82%;"><img id="azcEcrpkSWd8mQxChyeGE5" name="Ombraz Teton" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/azcEcrpkSWd8mQxChyeGE5-1920-80.png" mos="" align="middle" fullscreen="" width="1920" height="1283" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://lensandframe.co/products/ombraz-teton-prescription-eyeglasses-tortoise?" target="_blank" rel="nofollow" data-dimension112="943f142e-c8ab-11f1-b94c-098273589a7a" data-action="Deal Block" data-label="Teton (prescription)" data-dimension48="Teton (prescription)" data-dimension25="$470">Teton (prescription): $470</a></strong><br />The Ombraz Teton is a great option thanks to the reliable corded fit, and you can get them with photochromic or tinted lenses. The standard sunnies cost less than the prescription model if you do not use contact lenses.<a class="view-deal button" href="https://lensandframe.co/products/ombraz-teton-prescription-eyeglasses-tortoise?" target="_blank" rel="nofollow" data-dimension112="943f142e-c8ab-11f1-b94c-098273589a7a" data-action="Deal Block" data-label="Teton (prescription)" data-dimension48="Teton (prescription)" data-dimension25="$470">View Deal</a></p></div><h3 class="article-body__section" id="section-rudy-project-rydon-slim"><span>Rudy Project Rydon Slim</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="sHKUmdN5zmXteBoqvNy8BG" name="Rudy Project Rydon Slim Glasses" alt="Rudy Project Rydon Glasses" src="https://cdn.mos.cms.futurecdn.net/sHKUmdN5zmXteBoqvNy8BG-1920-80.jpg" mos="" align="middle" fullscreen="" width="4032" height="2268" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The Rudy Project Rydon Slim frames live up to their name with a very minimal style that’s incredibly light and comfortable to wear during workouts.</p><p>You can bend and adjust the nosepads and arms on the glasses to make the fit more secure, and you can get frames with prescription lenses, optical inserts, or (if you have a more demanding prescription) the optical dock I have on mine, which is why they have full frames.</p><p>I also have photochromic lenses on these glasses to make them more useful during the winter months here in the UK, where the sun can be a relatively rare sight.</p><p>These are another expensive option, but you get top-class lenses in an extremely light frame, and a wide variety of options for your lenses to suit different environments.</p><div class="product"><a data-dimension112="943f150a-c8ab-11f1-a1c4-33ca0829252b" data-action="Deal Block" data-label="Rydon Slim" data-dimension48="Rydon Slim" data-dimension25="$241" href="https://www.rudyprojectna.com/collections/rudy-project-best-selling-prescription-eyewear/products/rydon-slim" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:66.67%;"><img id="aVkivX5QYFmg7hzCPFh8bc" name="Rudy Project Rydon Slim" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/aVkivX5QYFmg7hzCPFh8bc-1920-80.png" mos="" align="middle" fullscreen="" width="1800" height="1200" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rudyprojectna.com/collections/rudy-project-best-selling-prescription-eyewear/products/rydon-slim" target="_blank" rel="nofollow" data-dimension112="943f150a-c8ab-11f1-a1c4-33ca0829252b" data-action="Deal Block" data-label="Rydon Slim" data-dimension48="Rydon Slim" data-dimension25="$241">Rydon Slim: $241</a></strong><br />These ultra-lightweight frames have different prescription options to suit different people, including the optical dock setup I needed with my high prescription. <a class="view-deal button" href="https://www.rudyprojectna.com/collections/rudy-project-best-selling-prescription-eyewear/products/rydon-slim" target="_blank" rel="nofollow" data-dimension112="943f150a-c8ab-11f1-a1c4-33ca0829252b" data-action="Deal Block" data-label="Rydon Slim" data-dimension48="Rydon Slim" data-dimension25="$241">View Deal</a></p></div><h3 class="article-body__section" id="section-lensdirect-diablo-topspin"><span>LensDirect Diablo Topspin</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="6Bi4bDmM73xqw6A6sRe2vF" name="LensDirect Diablo Topspin" alt="LensDirect Diablo Topspin" src="https://cdn.mos.cms.futurecdn.net/6Bi4bDmM73xqw6A6sRe2vF-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The Diablo line-up from LensDirect contains frames built for active lifestyles, all of which have a less sporty look than the other options I’ve picked out here.</p><p>As a result, the fit on the Topspin isn’t quite as secure as my other picks, but they are suitable for general use alongside workouts. I’ve done a couple of races with them along with a lot of training runs.</p><p>I found I had to nudge them back up my nose at times during runs, but the fit is pretty good, and I like the style of the Topspin. I was also impressed by the VoltPRO color-enhancing lenses, especially on trail runs under tree cover.</p><p>The Topspin sunglasses are also good value, though you do pay a bit more if you opt for the VoltPRO lenses.</p><div class="product"><a data-dimension112="943f15be-c8ab-11f1-a22a-055228e93979" data-action="Deal Block" data-label="Diablo Topspin" data-dimension48="Diablo Topspin" data-dimension25="$95" href="https://www.lensdirect.com/topspin-rubberized-matte-black" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2500px;"><p class="vanilla-image-block" style="padding-top:50.00%;"><img id="fVSmnR2aB7bFapaNVrUghQ" name="LensDirect Diablo Topspin" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/fVSmnR2aB7bFapaNVrUghQ-1920-80.png" mos="" align="middle" fullscreen="" width="2500" height="1250" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.lensdirect.com/topspin-rubberized-matte-black" target="_blank" rel="nofollow" data-dimension112="943f15be-c8ab-11f1-a22a-055228e93979" data-action="Deal Block" data-label="Diablo Topspin" data-dimension48="Diablo Topspin" data-dimension25="$95">Diablo Topspin: $95</a></strong><br />The Topspin frames are a good option for those who want sports sunglasses they can use outside their training, too, thanks to their stylish design. <a class="view-deal button" href="https://www.lensdirect.com/topspin-rubberized-matte-black" target="_blank" rel="nofollow" data-dimension112="943f15be-c8ab-11f1-a22a-055228e93979" data-action="Deal Block" data-label="Diablo Topspin" data-dimension48="Diablo Topspin" data-dimension25="$95">View Deal</a></p></div><h3 class="article-body__section" id="section-reks-sling-blade"><span>REKS Sling Blade</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="uS2i8BXQLAQaoev4nLGQJG" name="REKS Sling Blade" alt="REKS Sling Blade" src="https://cdn.mos.cms.futurecdn.net/uS2i8BXQLAQaoev4nLGQJG-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The REKS Sling Blade sunglasses are particularly robust and make for a good pick if durability is a top concern.</p><p>They are another affordable option I’ve been impressed by, with a sporty style and a wide variety of lens options, including the photochromic ones I went for, along with a variety of sunglasses tints designed for different activities.</p><p>I prefer the fit and style of the Zenni Zunnies myself, but the Sling Blade did stay in place pretty well, and the thicker frame and lenses on the REKS specs are part of the reason they’re so durable.</p><div class="product"><a data-dimension112="dcd30d62-c8ab-11f1-9416-bdc7d6a5ab67" data-action="Deal Block" data-label="Sling Blade" data-dimension48="Sling Blade" data-dimension25="$95" href="https://reks.com/products/sling-blade-sunglasses-hd-polycarbonate?variant=33006087077947" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="BjJRtD9oMZn7Kh938x2UPa" name="REKS Sling Blade" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/BjJRtD9oMZn7Kh938x2UPa-1920-80.png" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Sling Blade glasses are particularly durable thanks to thick frames and lenses, so they will serve you well if you're engaged in more adventurous activities.<a class="view-deal button" href="https://reks.com/products/sling-blade-sunglasses-hd-polycarbonate?variant=33006087077947" target="_blank" rel="nofollow" data-dimension112="dcd30d62-c8ab-11f1-9416-bdc7d6a5ab67" data-action="Deal Block" data-label="Sling Blade" data-dimension48="Sling Blade" data-dimension25="$95">View Deal</a></p></div><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-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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/smartwatches/i-tested-the-garmin-forerunner-970-vs-coros-pace-4-pro-which-should-you-buy"><strong>I tested the Garmin Forerunner 970 vs Coros Pace 4 Pro — which should you buy?</strong></a></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/running/ive-tested-the-hoka-clifton-11-vs-hoka-bondi-9-and-this-is-the-one-id-buy"><strong>I’ve tested the Hoka Clifton 11 vs Hoka Bondi 9 and this is the one I’d buy</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/running/my-favorite-trail-running-shoe-is-34-percent-off-for-prime-day-and-its-great-for-hiking-too"><strong>My favorite trail-running shoe is 34% off for Prime Day, and it’s great for hiking too</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/running/i-ran-hundreds-of-miles-with-5-pairs-of-prescription-sports-sunglasses-these-are-the-best-ones-to-buy</link>
                                                                            <description>
                            <![CDATA[ Ditch the contact lenses and get a set of proper sports sunglasses for the best experience during runs and other workouts. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">CPcxzrhWAK6esKAezceCR</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/vcytf7UkVPQfpMimzei6qS-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 19 Oct 2026 07:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Running]]></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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/vcytf7UkVPQfpMimzei6qS-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Zenni Optical Zunnies Wrap-Around Sunglasses]]></media:description>                                                            <media:text><![CDATA[Zenni Optical Zunnies Wrap-Around Sunglasses]]></media:text>
                                <media:title type="plain"><![CDATA[Zenni Optical Zunnies Wrap-Around Sunglasses]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/vcytf7UkVPQfpMimzei6qS-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>If you’re short- or long-sighted, active and have never invested in a set of prescription sports sunglasses or glasses, I’m here to tell you that it’s a game-changer.</p><p>I’ve been running more or less daily for over 10 years and only really caught on to prescription sports sunnies in the last five years, and they make each and every workout more enjoyable.</p><p>In the distant past, I just used my regular glasses, which slipped down my nose, bounced and didn’t work with doses of heavy sweating. </p><p>Of course I’ve also tried contact lenses, but they’re a hassle and an expensive option just to use for runs, since I don’t find them comfortable to wear all day.</p><p>I’ve now tested a lot of different prescription sports sunglasses, and I’ve covered the pros and cons of five of my favorite sets below after running hundreds of miles with them as well as cycling.</p><h3 class="article-body__section" id="section-zenni-optical-zunnies-wrap-around-sports-sunglasses"><span>Zenni Optical Zunnies Wrap-Around Sports Sunglasses</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:2189px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="KsngQTMvES2JHeWPfetw4G" name="Zenni Optical Zunnies Wrap-Around Sunglasses" alt="Zenni Optical Zunnies Wrap-Around Sunglasses" src="https://cdn.mos.cms.futurecdn.net/v2/w:1920,t:111,l:180,cw:2189,ch:1231,q:80/KsngQTMvES2JHeWPfetw4G.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>I have three pairs of these sunglasses, the last of which I bought just to get them in a color I prefer for races, which gives you some indication of how much I like them.</p><p>Zenni’s Zunnies line-up contains some of the best value prescription sports sunglasses and glasses I’ve come across, and these lightweight wraparound sunnies hit all the key markers I look for.</p><p>The fit is perfect, with the sunglasses staying firmly in place over runs of any length (including marathons in my testing) without any pressure points.</p><p>There’s a variety of lens styles and tints to pick from, and you can choose standard or wider lenses to suit your face. Whatever combo you opt for, the price stays south of $150, and many sets will cost you less than $100. For most people, these would be my top pick.</p><div class="product"><a data-dimension112="be5e88ee-c8aa-11f1-b619-c5611a5ee28b" data-action="Deal Block" data-label="Zunnies Wrap-Around Sunglasses" data-dimension48="Zunnies Wrap-Around Sunglasses" data-dimension25="$23.95" href="https://www.zennioptical.com/p/halfrim-plastic-wrap-around-sunglass-frames/10134/1013421" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1200px;"><p class="vanilla-image-block" style="padding-top:31.17%;"><img id="QzGZbGXZ9qawtm89ngyFtS" name="Zenni Optical Zunnies Wrap-Around Sunglasses" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/QzGZbGXZ9qawtm89ngyFtS-1920-80.png" mos="" align="middle" fullscreen="" width="1200" height="374" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.zennioptical.com/p/halfrim-plastic-wrap-around-sunglass-frames/10134/1013421" target="_blank" rel="nofollow" data-dimension112="be5e88ee-c8aa-11f1-b619-c5611a5ee28b" data-action="Deal Block" data-label="Zunnies Wrap-Around Sunglasses" data-dimension48="Zunnies Wrap-Around Sunglasses" data-dimension25="$23.95">Zunnies Wrap-Around Sunglasses: $23.95</a></strong><br />These Zenni Zunnies are my prescription running sunglasses overall, partly thanks to the great value they offer. Even with prescription lenses, you'll probably only have to pay around $80-$130, depending on the lenses you opt for.<a class="view-deal button" href="https://www.zennioptical.com/p/halfrim-plastic-wrap-around-sunglass-frames/10134/1013421" target="_blank" rel="nofollow" data-dimension112="be5e88ee-c8aa-11f1-b619-c5611a5ee28b" data-action="Deal Block" data-label="Zunnies Wrap-Around Sunglasses" data-dimension48="Zunnies Wrap-Around Sunglasses" data-dimension25="$23.95">View Deal</a></p></div><h3 class="article-body__section" id="section-ombraz-teton"><span>Ombraz Teton</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:3972px;"><p class="vanilla-image-block" style="padding-top:56.24%;"><img id="YnFyULgnuQBKYe2VJonf69" name="Ombraz Teton Sunglasses" alt="Ombraz Teton Sunglasses" src="https://cdn.mos.cms.futurecdn.net/YnFyULgnuQBKYe2VJonf69-1920-80.jpg" mos="" align="middle" fullscreen="" width="3972" height="2234" 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>Ombraz’s line-up of sunglasses uses a cord instead of arms, and this is a brilliantly simple and effective way to get a guaranteed great fit for sports.</p><p>I’ve used the Teton regularly throughout my current marathon training block, and I have them with photochromic lenses so I can actually wear them for indoor runs, bike rides and night runs.</p><p>The fit is quick and easy to adjust, and you don’t have to tighten the cord so much that it puts any pressure on your head to ensure the Teton sunnies stay in place.</p><p>They’re also stylish sunglasses for general use, and because they don’t have arms, they pack away in a flat case, so they’re easy to take on trips.</p><p>The price for the prescription version of the sunglasses is high, though, several times what you pay for the standard Ombraz Teton with normal lenses.</p><div class="product"><a data-dimension112="943f142e-c8ab-11f1-b94c-098273589a7a" data-action="Deal Block" data-label="Teton (prescription)" data-dimension48="Teton (prescription)" data-dimension25="$470" href="https://lensandframe.co/products/ombraz-teton-prescription-eyeglasses-tortoise?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:66.82%;"><img id="azcEcrpkSWd8mQxChyeGE5" name="Ombraz Teton" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/azcEcrpkSWd8mQxChyeGE5-1920-80.png" mos="" align="middle" fullscreen="" width="1920" height="1283" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://lensandframe.co/products/ombraz-teton-prescription-eyeglasses-tortoise?" target="_blank" rel="nofollow" data-dimension112="943f142e-c8ab-11f1-b94c-098273589a7a" data-action="Deal Block" data-label="Teton (prescription)" data-dimension48="Teton (prescription)" data-dimension25="$470">Teton (prescription): $470</a></strong><br />The Ombraz Teton is a great option thanks to the reliable corded fit, and you can get them with photochromic or tinted lenses. The standard sunnies cost less than the prescription model if you do not use contact lenses.<a class="view-deal button" href="https://lensandframe.co/products/ombraz-teton-prescription-eyeglasses-tortoise?" target="_blank" rel="nofollow" data-dimension112="943f142e-c8ab-11f1-b94c-098273589a7a" data-action="Deal Block" data-label="Teton (prescription)" data-dimension48="Teton (prescription)" data-dimension25="$470">View Deal</a></p></div><h3 class="article-body__section" id="section-rudy-project-rydon-slim"><span>Rudy Project Rydon Slim</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="sHKUmdN5zmXteBoqvNy8BG" name="Rudy Project Rydon Slim Glasses" alt="Rudy Project Rydon Glasses" src="https://cdn.mos.cms.futurecdn.net/sHKUmdN5zmXteBoqvNy8BG-1920-80.jpg" mos="" align="middle" fullscreen="" width="4032" height="2268" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The Rudy Project Rydon Slim frames live up to their name with a very minimal style that’s incredibly light and comfortable to wear during workouts.</p><p>You can bend and adjust the nosepads and arms on the glasses to make the fit more secure, and you can get frames with prescription lenses, optical inserts, or (if you have a more demanding prescription) the optical dock I have on mine, which is why they have full frames.</p><p>I also have photochromic lenses on these glasses to make them more useful during the winter months here in the UK, where the sun can be a relatively rare sight.</p><p>These are another expensive option, but you get top-class lenses in an extremely light frame, and a wide variety of options for your lenses to suit different environments.</p><div class="product"><a data-dimension112="943f150a-c8ab-11f1-a1c4-33ca0829252b" data-action="Deal Block" data-label="Rydon Slim" data-dimension48="Rydon Slim" data-dimension25="$241" href="https://www.rudyprojectna.com/collections/rudy-project-best-selling-prescription-eyewear/products/rydon-slim" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1800px;"><p class="vanilla-image-block" style="padding-top:66.67%;"><img id="aVkivX5QYFmg7hzCPFh8bc" name="Rudy Project Rydon Slim" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/aVkivX5QYFmg7hzCPFh8bc-1920-80.png" mos="" align="middle" fullscreen="" width="1800" height="1200" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rudyprojectna.com/collections/rudy-project-best-selling-prescription-eyewear/products/rydon-slim" target="_blank" rel="nofollow" data-dimension112="943f150a-c8ab-11f1-a1c4-33ca0829252b" data-action="Deal Block" data-label="Rydon Slim" data-dimension48="Rydon Slim" data-dimension25="$241">Rydon Slim: $241</a></strong><br />These ultra-lightweight frames have different prescription options to suit different people, including the optical dock setup I needed with my high prescription. <a class="view-deal button" href="https://www.rudyprojectna.com/collections/rudy-project-best-selling-prescription-eyewear/products/rydon-slim" target="_blank" rel="nofollow" data-dimension112="943f150a-c8ab-11f1-a1c4-33ca0829252b" data-action="Deal Block" data-label="Rydon Slim" data-dimension48="Rydon Slim" data-dimension25="$241">View Deal</a></p></div><h3 class="article-body__section" id="section-lensdirect-diablo-topspin"><span>LensDirect Diablo Topspin</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="6Bi4bDmM73xqw6A6sRe2vF" name="LensDirect Diablo Topspin" alt="LensDirect Diablo Topspin" src="https://cdn.mos.cms.futurecdn.net/6Bi4bDmM73xqw6A6sRe2vF-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The Diablo line-up from LensDirect contains frames built for active lifestyles, all of which have a less sporty look than the other options I’ve picked out here.</p><p>As a result, the fit on the Topspin isn’t quite as secure as my other picks, but they are suitable for general use alongside workouts. I’ve done a couple of races with them along with a lot of training runs.</p><p>I found I had to nudge them back up my nose at times during runs, but the fit is pretty good, and I like the style of the Topspin. I was also impressed by the VoltPRO color-enhancing lenses, especially on trail runs under tree cover.</p><p>The Topspin sunglasses are also good value, though you do pay a bit more if you opt for the VoltPRO lenses.</p><div class="product"><a data-dimension112="943f15be-c8ab-11f1-a22a-055228e93979" data-action="Deal Block" data-label="Diablo Topspin" data-dimension48="Diablo Topspin" data-dimension25="$95" href="https://www.lensdirect.com/topspin-rubberized-matte-black" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2500px;"><p class="vanilla-image-block" style="padding-top:50.00%;"><img id="fVSmnR2aB7bFapaNVrUghQ" name="LensDirect Diablo Topspin" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/fVSmnR2aB7bFapaNVrUghQ-1920-80.png" mos="" align="middle" fullscreen="" width="2500" height="1250" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.lensdirect.com/topspin-rubberized-matte-black" target="_blank" rel="nofollow" data-dimension112="943f15be-c8ab-11f1-a22a-055228e93979" data-action="Deal Block" data-label="Diablo Topspin" data-dimension48="Diablo Topspin" data-dimension25="$95">Diablo Topspin: $95</a></strong><br />The Topspin frames are a good option for those who want sports sunglasses they can use outside their training, too, thanks to their stylish design. <a class="view-deal button" href="https://www.lensdirect.com/topspin-rubberized-matte-black" target="_blank" rel="nofollow" data-dimension112="943f15be-c8ab-11f1-a22a-055228e93979" data-action="Deal Block" data-label="Diablo Topspin" data-dimension48="Diablo Topspin" data-dimension25="$95">View Deal</a></p></div><h3 class="article-body__section" id="section-reks-sling-blade"><span>REKS Sling Blade</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:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="uS2i8BXQLAQaoev4nLGQJG" name="REKS Sling Blade" alt="REKS Sling Blade" src="https://cdn.mos.cms.futurecdn.net/uS2i8BXQLAQaoev4nLGQJG-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Future)</span></figcaption></figure><p>The REKS Sling Blade sunglasses are particularly robust and make for a good pick if durability is a top concern.</p><p>They are another affordable option I’ve been impressed by, with a sporty style and a wide variety of lens options, including the photochromic ones I went for, along with a variety of sunglasses tints designed for different activities.</p><p>I prefer the fit and style of the Zenni Zunnies myself, but the Sling Blade did stay in place pretty well, and the thicker frame and lenses on the REKS specs are part of the reason they’re so durable.</p><div class="product"><a data-dimension112="dcd30d62-c8ab-11f1-9416-bdc7d6a5ab67" data-action="Deal Block" data-label="Sling Blade" data-dimension48="Sling Blade" data-dimension25="$95" href="https://reks.com/products/sling-blade-sunglasses-hd-polycarbonate?variant=33006087077947" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="BjJRtD9oMZn7Kh938x2UPa" name="REKS Sling Blade" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/BjJRtD9oMZn7Kh938x2UPa-1920-80.png" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Sling Blade glasses are particularly durable thanks to thick frames and lenses, so they will serve you well if you're engaged in more adventurous activities.<a class="view-deal button" href="https://reks.com/products/sling-blade-sunglasses-hd-polycarbonate?variant=33006087077947" target="_blank" rel="nofollow" data-dimension112="dcd30d62-c8ab-11f1-9416-bdc7d6a5ab67" data-action="Deal Block" data-label="Sling Blade" data-dimension48="Sling Blade" data-dimension25="$95">View Deal</a></p></div><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-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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/smartwatches/i-tested-the-garmin-forerunner-970-vs-coros-pace-4-pro-which-should-you-buy"><strong>I tested the Garmin Forerunner 970 vs Coros Pace 4 Pro — which should you buy?</strong></a></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/running/ive-tested-the-hoka-clifton-11-vs-hoka-bondi-9-and-this-is-the-one-id-buy"><strong>I’ve tested the Hoka Clifton 11 vs Hoka Bondi 9 and this is the one I’d buy</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/running/my-favorite-trail-running-shoe-is-34-percent-off-for-prime-day-and-its-great-for-hiking-too"><strong>My favorite trail-running shoe is 34% off for Prime Day, and it’s great for hiking too</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 'This is the simplest 3-move kettlebell workout you'll do', says a personal trainer, 'but the hardest' ]]></title>
                                                                                                <dc:content><![CDATA[ <p>You don't need a long list of kettlebell exercises or a complex workout that requires your trainer to repeat themselves 60 times before you understand it. You just need one of the <a href="https://www.tomsguide.com/best-picks/best-kettlebells">best kettlebells. </a>And some guts. Intrigued?</p><p>As a personal trainer, I like my clients to move functionally. That means I prioritize movements like cleans, squats, presses and rows that target the major muscle groups. I also like to improve conditioning, so this routine includes functional compound exercises, very little rest and <em>a lot </em>of pace. </p><p>Here it is.</p><h2 id="how-to-do-the-kettlebell-workout">How to do the kettlebell workout </h2><p>Set a <strong>12-minute timer</strong> (adjust to your taste) and grab a medium-heavy kettlebell. You'll be racking up reps, so choose a weight you can lift for about 10-12 reps rather than just a few. </p><p>Remember, you're going to fatigue, so aim for consistency rather than all-out intensity at first. You can ramp it up at the end, but aim for a slow burn at the start. This one will fire up almost every muscle group in your body, test stability and power and get your lungs and heart pumping.</p><p>At the end, you may want to lie down and bring your breathing under control while those jelly legs recover.</p><p>If you experience pain, feel dizzy or unwell, or are returning to exercise from illness or injury, please seek advice before starting this routine. If you are pregnant or post-partum, I strongly advise seeking medical advice.</p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="vGnNDN" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><div><blockquote><p>You may want to lie down and bring your breathing under control while those jelly legs recover.</p></blockquote></div><p><u><strong>Here are the moves broken down:</strong></u></p><ul><li><strong>Squat clean: </strong>Stand with your feet roughly hip- or shoulder-width apart. Grip a kettlebell between your feet. Drive the weight upward using an overhand grip, as if zipping up a jacket. As the kettlebell rests on your forearm, shelve it with your shoulder and perform a squat, keeping your elbow lifted and core engaged. Release the weight to the ground, then repeat on the other side.</li><li><strong>Down-up x bent-over row: </strong>Stand with your feet hip-width apart, place your hands down on the floor in front of you, then jump back into a plank with your core engaged. Jump your feet forward to land wide either side of your kettlebell. Row the weight with one arm, keeping your elbow close to your body. Lower it, repeat the down-up, then row with your other arm.</li><li><strong>Swing x squat clean x push press x overhead squat combo: </strong>Stand with your feet roughly hip- or shoulder-width apart. Grip a kettlebell between your feet. Drive the weight upward using an overhand grip, as if zipping up a jacket. As the kettlebell rests on your forearm, shelve it with your shoulder and perform a squat, keeping your elbow lifted and core engaged. Press the weight overhead using a soft knee drive, then perform a squat again, keeping your arm punched overhead close to your ear. Repeat on the other side.</li></ul><iframe src="https://content.jwplatform.com/players/nYFbjM7w.html" id="nYFbjM7w" title="Fire kettlebell workout" width="540" height="960" frameborder="0" scrolling="auto" allowfullscreen=""></iframe><p>Your goal is to complete 2 reps (a rep per side) of each move, back-to-back, in your first round. Reset. On the next round, add 2 reps. Keep adding each round, completing the moves back-to-back with no rest except between rounds. See how many rounds you can achieve in 12 minutes. </p><p>This is a killer workout, and you'll burn out fast if you don't pace yourself.</p><p>Focus on your form, engage your core for stability and power throughout, and try to maximize your squat depth. Always choose form over weight, and reduce it when you need to. If you reach your maximum, stick with the same reps rather than adding. </p><p>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 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/DelpZe0Tk3F/" target="_blank">A post shared by Tom's Guide Fitness | Workout Tips &amp; Gear (@tomsguidefitness)</a></p><p>A photo posted by </p></blockquote></div><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.js" async=""></script><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-to-be-more-mobile-in-their-60s-and-70s-3-low-impact-exercises-you-should-start-with" target="_blank"><strong>I teach people to be more mobile in their 60s and 70s: 3 low-impact exercises you should start with</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness/forget-burpees-the-pilates-burpee-is-beginner-friendly-and-low-impact-and-youll-love-it" target="_blank"><strong>Forget burpees —the 'Pilates burpee' is beginner-friendly and low-impact (and you’ll love it)</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/a-yoga-instructor-says-this-is-the-5-minute-yoga-routine-you-need-for-strong-and-mobile-hips-and-core-muscles" target="_blank"><strong>A yoga instructor says this is the 5-minute yoga routine you need for strong and mobile hips and core muscles</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/workouts/this-is-the-simplest-3-move-kettlebell-workout-youll-do-says-a-personal-trainer-but-the-hardest</link>
                                                                            <description>
                            <![CDATA[ A coach shares the kettlebell routine she recommends to challenge your body and get stronger without fussy or overcomplicated workouts. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">jRShLimWAGR9icZLDATVfJ</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/Ma98JkRxHrkpnJrkG2UGx9-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Mon, 19 Oct 2026 05:00:00 +0000</pubDate>                                                                                                                                <updated>Mon, 19 Oct 2026 10:06: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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/Ma98JkRxHrkpnJrkG2UGx9-1920-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Woman in purple workout clothes holding a kettlebell in front of her with both hands against grey backdrop]]></media:description>                                                            <media:text><![CDATA[Woman in purple workout clothes holding a kettlebell in front of her with both hands against grey backdrop]]></media:text>
                                <media:title type="plain"><![CDATA[Woman in purple workout clothes holding a kettlebell in front of her with both hands against grey backdrop]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/Ma98JkRxHrkpnJrkG2UGx9-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>You don't need a long list of kettlebell exercises or a complex workout that requires your trainer to repeat themselves 60 times before you understand it. You just need one of the <a href="https://www.tomsguide.com/best-picks/best-kettlebells">best kettlebells. </a>And some guts. Intrigued?</p><p>As a personal trainer, I like my clients to move functionally. That means I prioritize movements like cleans, squats, presses and rows that target the major muscle groups. I also like to improve conditioning, so this routine includes functional compound exercises, very little rest and <em>a lot </em>of pace. </p><p>Here it is.</p><h2 id="how-to-do-the-kettlebell-workout">How to do the kettlebell workout </h2><p>Set a <strong>12-minute timer</strong> (adjust to your taste) and grab a medium-heavy kettlebell. You'll be racking up reps, so choose a weight you can lift for about 10-12 reps rather than just a few. </p><p>Remember, you're going to fatigue, so aim for consistency rather than all-out intensity at first. You can ramp it up at the end, but aim for a slow burn at the start. This one will fire up almost every muscle group in your body, test stability and power and get your lungs and heart pumping.</p><p>At the end, you may want to lie down and bring your breathing under control while those jelly legs recover.</p><p>If you experience pain, feel dizzy or unwell, or are returning to exercise from illness or injury, please seek advice before starting this routine. If you are pregnant or post-partum, I strongly advise seeking medical advice.</p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="vGnNDN" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><div><blockquote><p>You may want to lie down and bring your breathing under control while those jelly legs recover.</p></blockquote></div><p><u><strong>Here are the moves broken down:</strong></u></p><ul><li><strong>Squat clean: </strong>Stand with your feet roughly hip- or shoulder-width apart. Grip a kettlebell between your feet. Drive the weight upward using an overhand grip, as if zipping up a jacket. As the kettlebell rests on your forearm, shelve it with your shoulder and perform a squat, keeping your elbow lifted and core engaged. Release the weight to the ground, then repeat on the other side.</li><li><strong>Down-up x bent-over row: </strong>Stand with your feet hip-width apart, place your hands down on the floor in front of you, then jump back into a plank with your core engaged. Jump your feet forward to land wide either side of your kettlebell. Row the weight with one arm, keeping your elbow close to your body. Lower it, repeat the down-up, then row with your other arm.</li><li><strong>Swing x squat clean x push press x overhead squat combo: </strong>Stand with your feet roughly hip- or shoulder-width apart. Grip a kettlebell between your feet. Drive the weight upward using an overhand grip, as if zipping up a jacket. As the kettlebell rests on your forearm, shelve it with your shoulder and perform a squat, keeping your elbow lifted and core engaged. Press the weight overhead using a soft knee drive, then perform a squat again, keeping your arm punched overhead close to your ear. Repeat on the other side.</li></ul><iframe src="https://content.jwplatform.com/players/nYFbjM7w.html" id="nYFbjM7w" title="Fire kettlebell workout" width="540" height="960" frameborder="0" scrolling="auto" allowfullscreen=""></iframe><p>Your goal is to complete 2 reps (a rep per side) of each move, back-to-back, in your first round. Reset. On the next round, add 2 reps. Keep adding each round, completing the moves back-to-back with no rest except between rounds. See how many rounds you can achieve in 12 minutes. </p><p>This is a killer workout, and you'll burn out fast if you don't pace yourself.</p><p>Focus on your form, engage your core for stability and power throughout, and try to maximize your squat depth. Always choose form over weight, and reduce it when you need to. If you reach your maximum, stick with the same reps rather than adding. </p><p>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 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/DelpZe0Tk3F/" target="_blank">A post shared by Tom's Guide Fitness | Workout Tips &amp; Gear (@tomsguidefitness)</a></p><p>A photo posted by </p></blockquote></div><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.js" async=""></script><h2 class="article-body__section" id="section-more-from-tom-s-guide"><span>More from Tom's Guide</span></h2><ul><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-to-be-more-mobile-in-their-60s-and-70s-3-low-impact-exercises-you-should-start-with" target="_blank"><strong>I teach people to be more mobile in their 60s and 70s: 3 low-impact exercises you should start with</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/fitness/forget-burpees-the-pilates-burpee-is-beginner-friendly-and-low-impact-and-youll-love-it" target="_blank"><strong>Forget burpees —the 'Pilates burpee' is beginner-friendly and low-impact (and you’ll love it)</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/a-yoga-instructor-says-this-is-the-5-minute-yoga-routine-you-need-for-strong-and-mobile-hips-and-core-muscles" target="_blank"><strong>A yoga instructor says this is the 5-minute yoga routine you need for strong and mobile hips and core muscles</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ 29 best running shoe deals for fall — up to 50% off Asics, Brooks, Hoka and more ]]></title>
                                                                                                <dc:content><![CDATA[ <p>In the market for a new pair of running sneakers? Well, you're in luck! Top brands like New Balance, Asics, Brooks and more are hosting huge sales — and many styles are available to snag right now on Amazon. </p><p>Whether you're hitting the trails, the pavement or the treadmill, there's a pair of sneakers for just about everyone — and select styles are up to 50% off as we speak. So don’t wait! These top deals won’t be around forever. Keep scrolling to shop the best running sneakers for fall. </p><p><strong>Note: </strong>prices vary depending on the size and color you choose; search the different color options available in your size to find the best deals.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links </span></h3><ul><li><strong>New Balance: </strong><a href="https://www.amazon.com/stores/page/855D4CDF-ADB7-4BE8-9E26-A085D029E4B5?" target="_blank" rel="nofollow"><strong>up to 50% off</strong></a></li><li><strong>Asics: </strong><a href="https://www.amazon.com/stores/page/848769B1-4C68-4CA5-B2E7-A4480A3FBF59" target="_blank" rel="nofollow"><strong>deals from $54</strong></a></li><li><strong>Adidas: </strong><a href="https://www.amazon.com/stores/adidas/page/5E398A61-45C7-46F9-A6C6-5B4797CC5063?" target="_blank" rel="nofollow"><strong>deals from $39</strong></a></li><li><strong>Brooks: </strong><a href="https://www.amazon.com/stores/Brooks/page/B6834DFA-396F-4E38-98F6-3D2739393271?" target="_blank" rel="nofollow"><strong>up to 40% off</strong></a></li><li><strong>Hoka: </strong><a href="https://www.hoka.com/en/us/sale/" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li><li><strong>Nike: </strong><a href="https://www.amazon.com/stores/page/E9C7C6A6-9A88-4959-A67F-4D44FC67320F" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li><li><strong>Saucony Tide 2 Trainer (Men's): </strong><a href="https://www.amazon.com/dp/B0D31XXWHZ?" target="_blank" rel="nofollow"><strong>was $100 now $65</strong></a></li><li><strong>Asics Glideride Max (Men's): </strong><a href="https://www.amazon.com/ASICS-GLIDERIDE-Running-Monument-Vanilla/dp/B0CT9HG8TB" target="_blank" rel="nofollow"><strong>was $170 now $89</strong></a></li><li><strong>Brooks Hyperion Max 3 (Men's): </strong><a href="https://www.amazon.com/Brooks-Mens-Hyperion-Neutral-Running/dp/B0DM3MTXGK?" target="_blank" rel="nofollow"><strong>was $199 now $108</strong></a></li><li><strong>New Balance FuelCell Trainer V3 (Women's): </strong><a href="https://www.amazon.com/New-Balance-FuelCell-SuperComp-Tangerine/dp/B0F4LZ7VDR" target="_blank" rel="nofollow"><strong>was $264 now $148</strong></a></li></ul><h3 class="article-body__section" id="section-best-new-balance-deals"><span>Best New Balance Deals</span></h3><div class="product"><a data-dimension112="2110009a-cb9d-11f1-8ff2-8d5dc4b13110" data-action="Deal Block" data-label="460 V4 Running Shoe (Women's)" data-dimension48="460 V4 Running Shoe (Women's)" data-dimension25="$48" href="https://www.amazon.com/New-Balance-Womens-Running-Orange/dp/B0CLB2MW44" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:842px;"><p class="vanilla-image-block" style="padding-top:53.09%;"><img id="oogbpG7TLGhF7fbRvzSZTn" name="460 V4 Running Shoe (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/oogbpG7TLGhF7fbRvzSZTn-1920-80.jpg" mos="" align="middle" fullscreen="" width="842" height="447" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-Womens-Running-Orange/dp/B0CLB2MW44" target="_blank" rel="nofollow" data-dimension112="2110009a-cb9d-11f1-8ff2-8d5dc4b13110" data-action="Deal Block" data-label="460 V4 Running Shoe (Women's)" data-dimension48="460 V4 Running Shoe (Women's)" data-dimension25="$48">460 V4 Running Shoe (Women's): was $64 now $48</a></strong><br />Despite their budget-friendly price, the New Balance 460 V4 are packed with soft cushioning and feature a supportive design. Reviewers on Amazon rave about how comfortable these shoes are.<a class="view-deal button" href="https://www.amazon.com/New-Balance-Womens-Running-Orange/dp/B0CLB2MW44" target="_blank" rel="nofollow" data-dimension112="2110009a-cb9d-11f1-8ff2-8d5dc4b13110" data-action="Deal Block" data-label="460 V4 Running Shoe (Women's)" data-dimension48="460 V4 Running Shoe (Women's)" data-dimension25="$48">View Deal</a></p></div><div class="product"><a data-dimension112="c01c42e8-c990-11f1-8eb6-0d66610eaa9e" data-action="Deal Block" data-label="410 V8 Trail Running Shoe (Men's)" data-dimension48="410 V8 Trail Running Shoe (Men's)" data-dimension25="$59" href="https://www.amazon.com/New-Balance-Running-Cayenne-Shadow/dp/B0D2BSMHB2" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:870px;"><p class="vanilla-image-block" style="padding-top:51.38%;"><img id="PnUcM3Fmgz2spyxFtnpAc6" name="image" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/PnUcM3Fmgz2spyxFtnpAc6-1920-80.png" mos="" align="middle" fullscreen="" width="870" height="447" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-Running-Cayenne-Shadow/dp/B0D2BSMHB2" target="_blank" rel="nofollow" data-dimension112="c01c42e8-c990-11f1-8eb6-0d66610eaa9e" data-action="Deal Block" data-label="410 V8 Trail Running Shoe (Men's)" data-dimension48="410 V8 Trail Running Shoe (Men's)" data-dimension25="$59">410 V8 Trail Running Shoe (Men's): was $69 now $59</a></strong><br />The New Balance 410 V8 trainer is a stylish running shoe to hit the trails with! These are kitted out with a soft bio foam in the midsole to keep you comfortable while pounding the trails and have strategic overlays to make sure you get the most out of the pair.<a class="view-deal button" href="https://www.amazon.com/New-Balance-Running-Cayenne-Shadow/dp/B0D2BSMHB2" target="_blank" rel="nofollow" data-dimension112="c01c42e8-c990-11f1-8eb6-0d66610eaa9e" data-action="Deal Block" data-label="410 V8 Trail Running Shoe (Men's)" data-dimension48="410 V8 Trail Running Shoe (Men's)" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="c01c436a-c990-11f1-8a29-331171a080ae" data-action="Deal Block" data-label="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension48="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension25="$108" href="https://www.amazon.com/New-Balance-FuelCell-Running-Afterglow/dp/B0F4LLKZCH" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:880px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="zMXtGm9YKG3arrNYXpTBH" name="New Balance Rebel v5 sq" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zMXtGm9YKG3arrNYXpTBH-1920-80.jpg" mos="" align="middle" fullscreen="" width="880" height="880" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-FuelCell-Running-Afterglow/dp/B0F4LLKZCH" target="_blank" rel="nofollow" data-dimension112="c01c436a-c990-11f1-8a29-331171a080ae" data-action="Deal Block" data-label="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension48="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension25="$108">FuelCell Rebel v5 Running Shoes (Women's): was $144 now $108</a></strong><br />The lightweight <a href="https://www.tomsguide.com/wellness/running/new-balance-rebel-v5-review">New Balance FuelCell Rebel v5</a> is a comfortable and speedy daily trainer that's perfect for those who don't love the feel of max-cushioned shoes, as it has a more grounded feel.<a class="view-deal button" href="https://www.amazon.com/New-Balance-FuelCell-Running-Afterglow/dp/B0F4LLKZCH" target="_blank" rel="nofollow" data-dimension112="c01c436a-c990-11f1-8a29-331171a080ae" data-action="Deal Block" data-label="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension48="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension25="$108">View Deal</a></p></div><div class="product"><a data-dimension112="c01c452c-c990-11f1-8eb9-b985c5a65cfe" data-action="Deal Block" data-label="Ellipse v1 (Men’s)" data-dimension48="Ellipse v1 (Men’s)" data-dimension25="$109" href="https://www.amazon.com/New-Balance-Ellipse-Running-Matter/dp/B0FX3DKKND" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:759px;"><p class="vanilla-image-block" style="padding-top:59.29%;"><img id="77VApTr9xqJVo2amFqMXdP" name="Ellipse v1 (Men’s)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/77VApTr9xqJVo2amFqMXdP-1920-80.jpg" mos="" align="middle" fullscreen="" width="759" height="450" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-Ellipse-Running-Matter/dp/B0FX3DKKND" target="_blank" rel="nofollow" data-dimension112="c01c452c-c990-11f1-8eb9-b985c5a65cfe" data-action="Deal Block" data-label="Ellipse v1 (Men’s)" data-dimension48="Ellipse v1 (Men’s)" data-dimension25="$109">Ellipse v1 (Men’s): was $145 now $109</a></strong><br />This everyday running shoe from New Balance is designed as much for beginners as it is for athletes. Featuring elevated cushioning in the midsole and a breathable engineered-mesh upper, it will work as well for a lunchtime 5K as it will for 5 a.m. marathon training. It's got an 8mm drop and a rockered profile for increased comfort.<a class="view-deal button" href="https://www.amazon.com/New-Balance-Ellipse-Running-Matter/dp/B0FX3DKKND" target="_blank" rel="nofollow" data-dimension112="c01c452c-c990-11f1-8eb9-b985c5a65cfe" data-action="Deal Block" data-label="Ellipse v1 (Men’s)" data-dimension48="Ellipse v1 (Men’s)" data-dimension25="$109">View Deal</a></p></div><div class="product"><a data-dimension112="c01c45d6-c990-11f1-ad42-2133b13010bd" data-action="Deal Block" data-label="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension48="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension25="$138" href="https://www.amazon.com/New-Balance-Running-Metallic-Inkwell/dp/B0CLB6X87W" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:880px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="XwbzzRSwcghwdApXRMQfb5" name="New Balance 1080v14 sq" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XwbzzRSwcghwdApXRMQfb5-1920-80.jpg" mos="" align="middle" fullscreen="" width="880" height="880" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-Running-Metallic-Inkwell/dp/B0CLB6X87W" target="_blank" rel="nofollow" data-dimension112="c01c45d6-c990-11f1-ad42-2133b13010bd" data-action="Deal Block" data-label="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension48="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension25="$138">Fresh Foam X 1080v14 Running Shoe (Men's): was $164 now $138</a></strong><br />The New Balance 1080v14 is a previous candidate on our list of the <a href="https://www.tomsguide.com/best-picks/best-running-shoes">best running shoes</a>. We gave it a 4-star rating in our <a href="https://www.tomsguide.com/wellness/running/new-balance-fresh-foam-x-1080v14-review">New Balance Fresh Foam X 1080v14 review</a>, saying that this is a cushioned daily trainer that offers a great balance of comfort and weight.<a class="view-deal button" href="https://www.amazon.com/New-Balance-Running-Metallic-Inkwell/dp/B0CLB6X87W" target="_blank" rel="nofollow" data-dimension112="c01c45d6-c990-11f1-ad42-2133b13010bd" data-action="Deal Block" data-label="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension48="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension25="$138">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4662-c990-11f1-a56f-f17a5ba42aed" data-action="Deal Block" data-label="FuelCell Supercomp Elite V5 (Women's)" data-dimension48="FuelCell Supercomp Elite V5 (Women's)" data-dimension25="$148" href="https://www.amazon.com/New-Balance-FuelCell-SuperComp-Tangerine/dp/B0F4LZ7VDR" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1267px;"><p class="vanilla-image-block" style="padding-top:54.85%;"><img id="BXfy6JhfauCEwEyTDyxFe3" name="FuelCell Supercomp Elite V5 (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/BXfy6JhfauCEwEyTDyxFe3-1920-80.jpg" mos="" align="middle" fullscreen="" width="1267" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-FuelCell-SuperComp-Tangerine/dp/B0F4LZ7VDR" target="_blank" rel="nofollow" data-dimension112="c01c4662-c990-11f1-a56f-f17a5ba42aed" data-action="Deal Block" data-label="FuelCell Supercomp Elite V5 (Women's)" data-dimension48="FuelCell Supercomp Elite V5 (Women's)" data-dimension25="$148">FuelCell Supercomp Elite V5 (Women's): was $264 now $148</a></strong><br />Our Fitness Editor, Jane McGuire, ran her fastest marathon in the Supercomp Elite V5 — and our Senior Fitness Writer, Nick Harris-Fry loved their lightweight, propulsive design in his <a href="https://www.tomsguide.com/wellness/running/new-balance-sc-elite-v5-review">New Balance FuelCell Supercomp Elite V5 review</a>. Don't sleep on this saving!<a class="view-deal button" href="https://www.amazon.com/New-Balance-FuelCell-SuperComp-Tangerine/dp/B0F4LZ7VDR" target="_blank" rel="nofollow" data-dimension112="c01c4662-c990-11f1-a56f-f17a5ba42aed" data-action="Deal Block" data-label="FuelCell Supercomp Elite V5 (Women's)" data-dimension48="FuelCell Supercomp Elite V5 (Women's)" data-dimension25="$148">View Deal</a></p></div><h3 class="article-body__section" id="section-best-asics-deals"><span>Best Asics Deals</span></h3><div class="product"><a data-dimension112="c01c475c-c990-11f1-b32c-e5dc07b29fb1" data-action="Deal Block" data-label="Gel-Kayano 30 (Women's)" data-dimension48="Gel-Kayano 30 (Women's)" data-dimension25="$69" href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1160px;"><p class="vanilla-image-block" style="padding-top:46.29%;"><img id="iHsvdtLnzyeWEyCZV8HBYe" name="Gel-Kayano 30 (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/iHsvdtLnzyeWEyCZV8HBYe-1920-80.jpg" mos="" align="middle" fullscreen="" width="1160" height="537" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow" data-dimension112="c01c475c-c990-11f1-b32c-e5dc07b29fb1" data-action="Deal Block" data-label="Gel-Kayano 30 (Women's)" data-dimension48="Gel-Kayano 30 (Women's)" data-dimension25="$69">Gel-Kayano 30 (Women's): was $160 now $69</a></strong><br />The Gel Kayano 30 running shoes are an older model, but they're amazingly cheap with 56% off. They're designed to provide advanced stability and soft cushioning for neutral runners and overpronators alike. Our Deals Editor-in-Chief, Louis Ramirez, wrote: "I've been using these shoes for almost two years now. (I loved them so much I bought a second pair months after buying my first pair). I find that they're great for casual runs on the treadmill, HIIT sessions, and long distance running outdoors."<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow" data-dimension112="c01c475c-c990-11f1-b32c-e5dc07b29fb1" data-action="Deal Block" data-label="Gel-Kayano 30 (Women's)" data-dimension48="Gel-Kayano 30 (Women's)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="c01c47d4-c990-11f1-8c7c-91286f932f4d" data-action="Deal Block" data-label="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension48="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension25="$69" href="https://www.amazon.com/ASICS-Gel-Contend-Running-Shoes-Black/dp/B0GGCWVYC7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:45.42%;"><img id="yyx3Rc6DdUotj8NTEwFwLa" name="Gel-Contend 10 Road Running Shoes (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/yyx3Rc6DdUotj8NTEwFwLa-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="525" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Gel-Contend-Running-Shoes-Black/dp/B0GGCWVYC7" target="_blank" rel="nofollow" data-dimension112="c01c47d4-c990-11f1-8c7c-91286f932f4d" data-action="Deal Block" data-label="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension48="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension25="$69">Gel-Contend 10 Road Running Shoes (Men's): was $80 now $69</a></strong><br />The 10th iteration of Asics' budget-friendly road running shoes have dropped in price! They feature Amplifoam+ cushioning to support your runs and have a lightweight and breathable mesh upper.<a class="view-deal button" href="https://www.amazon.com/ASICS-Gel-Contend-Running-Shoes-Black/dp/B0GGCWVYC7" target="_blank" rel="nofollow" data-dimension112="c01c47d4-c990-11f1-8c7c-91286f932f4d" data-action="Deal Block" data-label="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension48="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4856-c990-11f1-aabf-39c8fd6379ee" data-action="Deal Block" data-label="Women's Novablast 4" data-dimension48="Women's Novablast 4" data-dimension25="$67" href="https://www.amazon.com/ASICS-Womens-NOVABLAST-Running-Expanse/dp/B0CFP3J6RB" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1200px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="wMYSVC2325TPeXMt7TJ9t3" name="Asics Novablast 4" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/wMYSVC2325TPeXMt7TJ9t3-1920-80.jpg" mos="" align="middle" fullscreen="" width="1200" height="1200" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-NOVABLAST-Running-Expanse/dp/B0CFP3J6RB" target="_blank" rel="nofollow" data-dimension112="c01c4856-c990-11f1-aabf-39c8fd6379ee" data-action="Deal Block" data-label="Women's Novablast 4" data-dimension48="Women's Novablast 4" data-dimension25="$67">Women's Novablast 4: was $140 now $67</a></strong><br />Old but gold. While the Novablast 6 is now available, the Novablast 4 is beloved by the Tom's Guide team — especially our Fitness Editor Jane McGuire, who wrote: "I've run over 100 miles in this shoe, and it's still one I reach for when I'm heading out for a long run."<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-NOVABLAST-Running-Expanse/dp/B0CFP3J6RB" target="_blank" rel="nofollow" data-dimension112="c01c4856-c990-11f1-aabf-39c8fd6379ee" data-action="Deal Block" data-label="Women's Novablast 4" data-dimension48="Women's Novablast 4" data-dimension25="$67">View Deal</a></p></div><div class="product"><a data-dimension112="c01c48ce-c990-11f1-98e1-1d86104a3678" data-action="Deal Block" data-label="Glideride Max (Men's)" data-dimension48="Glideride Max (Men's)" data-dimension25="$80" href="https://www.amazon.com/ASICS-GLIDERIDE-Running-Monument-Vanilla/dp/B0CT9HG8TB" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1157px;"><p class="vanilla-image-block" style="padding-top:50.91%;"><img id="ur2nzvnBf49fo9rfEakkpK" name="Glideride Max (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ur2nzvnBf49fo9rfEakkpK-1920-80.jpg" mos="" align="middle" fullscreen="" width="1157" height="589" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-GLIDERIDE-Running-Monument-Vanilla/dp/B0CT9HG8TB" target="_blank" rel="nofollow" data-dimension112="c01c48ce-c990-11f1-98e1-1d86104a3678" data-action="Deal Block" data-label="Glideride Max (Men's)" data-dimension48="Glideride Max (Men's)" data-dimension25="$80">Glideride Max (Men's): was $170 now $80</a></strong><br />At 53% off, the Asics Glideride are a steal. These come with GuideSole tech to help you save energy, keeping you going for longer. You also get FF Blast Max cushioning for a lightweight, soft feel.<a class="view-deal button" href="https://www.amazon.com/ASICS-GLIDERIDE-Running-Monument-Vanilla/dp/B0CT9HG8TB" target="_blank" rel="nofollow" data-dimension112="c01c48ce-c990-11f1-98e1-1d86104a3678" data-action="Deal Block" data-label="Glideride Max (Men's)" data-dimension48="Glideride Max (Men's)" data-dimension25="$80">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4950-c990-11f1-90e0-a54efa81122b" data-action="Deal Block" data-label="Sonicblast Road Running Shoes (Men's)" data-dimension48="Sonicblast Road Running Shoes (Men's)" data-dimension25="$94" href="https://www.amazon.com/Asics-SONICBLAST-Running-Winter-Stillwater/dp/B0DPLQ32YV" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1528px;"><p class="vanilla-image-block" style="padding-top:75.00%;"><img id="rD9sdYvxaqtEV2BgyMfTx" name="Sonicblast" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/rD9sdYvxaqtEV2BgyMfTx-1920-80.jpg" mos="" align="middle" fullscreen="" width="1528" height="1146" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Asics-SONICBLAST-Running-Winter-Stillwater/dp/B0DPLQ32YV" target="_blank" rel="nofollow" data-dimension112="c01c4950-c990-11f1-90e0-a54efa81122b" data-action="Deal Block" data-label="Sonicblast Road Running Shoes (Men's)" data-dimension48="Sonicblast Road Running Shoes (Men's)" data-dimension25="$94">Sonicblast Road Running Shoes (Men's): was $180 now $94</a></strong><br />Suited for both fast runs and everyday training, the Asics Sonicblast are super lightweight and propulsive. There's an Astroplate mechanism to help you shoot forward, as well as FF Blast Max and FF Turbo cushioning for a bouncy feel underfoot.<a class="view-deal button" href="https://www.amazon.com/Asics-SONICBLAST-Running-Winter-Stillwater/dp/B0DPLQ32YV" target="_blank" rel="nofollow" data-dimension112="c01c4950-c990-11f1-90e0-a54efa81122b" data-action="Deal Block" data-label="Sonicblast Road Running Shoes (Men's)" data-dimension48="Sonicblast Road Running Shoes (Men's)" data-dimension25="$94">View Deal</a></p></div><div class="product"><a data-dimension112="211001a8-cb9d-11f1-9160-758de2e1b850" data-action="Deal Block" data-label="Novablast 5 (Men's)" data-dimension48="Novablast 5 (Men's)" data-dimension25="$129" href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1166px;"><p class="vanilla-image-block" style="padding-top:48.80%;"><img id="4pk4xESon4iEcQDmd7TqZF" name="Novablast 5 (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4pk4xESon4iEcQDmd7TqZF-1920-80.jpg" mos="" align="middle" fullscreen="" width="1166" height="569" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow" data-dimension112="211001a8-cb9d-11f1-9160-758de2e1b850" data-action="Deal Block" data-label="Novablast 5 (Men's)" data-dimension48="Novablast 5 (Men's)" data-dimension25="$129">Novablast 5 (Men's): was $160 now $129</a></strong><br />We voted the Asics Novablast 6 as the <a href="https://www.tomsguide.com/best-picks/best-running-shoes">best running shoes</a> you can buy right now, but before that, the <a href="https://www.tomsguide.com/wellness/running/asics-novablast-5-review">Asics Novablast 5</a> had the top spot. They quickly stood out for their balance of comfort, support and fun, making them a pair of shoes you will actually look forward to running in. They're lightweight, durable and have a soft, springy feel underfoot that helps absorb impact while keeping runs enjoyable.<a class="view-deal button" href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow" data-dimension112="211001a8-cb9d-11f1-9160-758de2e1b850" data-action="Deal Block" data-label="Novablast 5 (Men's)" data-dimension48="Novablast 5 (Men's)" data-dimension25="$129">View Deal</a></p></div><h3 class="article-body__section" id="section-best-brooks-deals"><span>Best Brooks Deals</span></h3><div class="product"><a data-dimension112="c01c4a40-c990-11f1-af5c-0dc2fe444d53" data-action="Deal Block" data-label="Caldera 8 Ultra Trail Running Shoe (Women's)" data-dimension48="Caldera 8 Ultra Trail Running Shoe (Women's)" data-dimension25="$89" href="https://www.amazon.com/Brooks-Womens-Caldera-Ultra-Running/dp/B0D3JB13WZ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1097px;"><p class="vanilla-image-block" style="padding-top:63.35%;"><img id="2djj2QHTebGwfGjm4tKjFa" name="Brooks Caldera" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/2djj2QHTebGwfGjm4tKjFa-1920-80.jpg" mos="" align="middle" fullscreen="" width="1097" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Brooks-Womens-Caldera-Ultra-Running/dp/B0D3JB13WZ" target="_blank" rel="nofollow" data-dimension112="c01c4a40-c990-11f1-af5c-0dc2fe444d53" data-action="Deal Block" data-label="Caldera 8 Ultra Trail Running Shoe (Women's)" data-dimension48="Caldera 8 Ultra Trail Running Shoe (Women's)" data-dimension25="$89">Caldera 8 Ultra Trail Running Shoe (Women's): was $149 now $89</a></strong><br />The Brooks Caldera 8 Ultra Trail is built for going the distance on uneven terrain. It has plenty of cushioning alongside all that necessary traction for tackling the trails, and it has high sidewalls to keep your feet nice and stable.<a class="view-deal button" href="https://www.amazon.com/Brooks-Womens-Caldera-Ultra-Running/dp/B0D3JB13WZ" target="_blank" rel="nofollow" data-dimension112="c01c4a40-c990-11f1-af5c-0dc2fe444d53" data-action="Deal Block" data-label="Caldera 8 Ultra Trail Running Shoe (Women's)" data-dimension48="Caldera 8 Ultra Trail Running Shoe (Women's)" data-dimension25="$89">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4b1c-c990-11f1-b7c6-2b0013333224" data-action="Deal Block" data-label="Hyperion Max 3 (Men's)" data-dimension48="Hyperion Max 3 (Men's)" data-dimension25="$108" href="https://www.amazon.com/dp/B0DM3MTXGK?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:840px;"><p class="vanilla-image-block" style="padding-top:68.45%;"><img id="bf7gzstL3kTG3roVNuaN4L" name="Brooks Hyperion Max" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bf7gzstL3kTG3roVNuaN4L-1920-80.png" mos="" align="middle" fullscreen="" width="840" height="575" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0DM3MTXGK?" target="_blank" rel="nofollow" data-dimension112="c01c4b1c-c990-11f1-b7c6-2b0013333224" data-action="Deal Block" data-label="Hyperion Max 3 (Men's)" data-dimension48="Hyperion Max 3 (Men's)" data-dimension25="$108">Hyperion Max 3 (Men's): was $199 now $108</a></strong><br />The Brooks Hyperion Max 3 is a plated training shoe with a mega-stack of cushioning in its midsole, the top layer of which is made from a particularly springy PEBA material. It's a speedier option than shoes like the Glycerin and Ghost, and still comfortable for easy runs as well.<a class="view-deal button" href="https://www.amazon.com/dp/B0DM3MTXGK?" target="_blank" rel="nofollow" data-dimension112="c01c4b1c-c990-11f1-b7c6-2b0013333224" data-action="Deal Block" data-label="Hyperion Max 3 (Men's)" data-dimension48="Hyperion Max 3 (Men's)" data-dimension25="$108">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4b9e-c990-11f1-ae63-71c4afc87ea1" data-action="Deal Block" data-label="Ghost Max 3 (Men's)" data-dimension48="Ghost Max 3 (Men's)" data-dimension25="$109" href="https://www.amazon.com/dp/B0DM3R7VD1?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:890px;"><p class="vanilla-image-block" style="padding-top:64.61%;"><img id="mL6eZbPdx2NmSyzvQSMAcc" name="Brooks Ghost Max 3" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/mL6eZbPdx2NmSyzvQSMAcc-1920-80.png" mos="" align="middle" fullscreen="" width="890" height="575" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0DM3R7VD1?" target="_blank" rel="nofollow" data-dimension112="c01c4b9e-c990-11f1-ae63-71c4afc87ea1" data-action="Deal Block" data-label="Ghost Max 3 (Men's)" data-dimension48="Ghost Max 3 (Men's)" data-dimension25="$109">Ghost Max 3 (Men's): was $159 now $109</a></strong><br />The Ghost Max 3 is a more cushioned and rockered alternative to the Ghost 17, and I prefer the ride of the shoe myself to the classic Ghost. The Ghost Max 4 has just come out, meaning the Ghost Max 3 is reduced by $50, with almost all colors and sizes included in the sale.<a class="view-deal button" href="https://www.amazon.com/dp/B0DM3R7VD1?" target="_blank" rel="nofollow" data-dimension112="c01c4b9e-c990-11f1-ae63-71c4afc87ea1" data-action="Deal Block" data-label="Ghost Max 3 (Men's)" data-dimension48="Ghost Max 3 (Men's)" data-dimension25="$109">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4c16-c990-11f1-bc3b-e7f4af19bbfb" data-action="Deal Block" data-label="Glycerin Max (Women's)" data-dimension48="Glycerin Max (Women's)" data-dimension25="$149" href="https://www.amazon.com/Brooks-Womens-Glycerin-Peacoat-Ribbon/dp/B0D3B6HXJ7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:926px;"><p class="vanilla-image-block" style="padding-top:62.10%;"><img id="Y98AvyBg8eBD4Re2iRNXC6" name="Brooks Gycerin Max" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Y98AvyBg8eBD4Re2iRNXC6-1920-80.png" mos="" align="middle" fullscreen="" width="926" height="575" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Brooks-Womens-Glycerin-Peacoat-Ribbon/dp/B0D3B6HXJ7" target="_blank" rel="nofollow" data-dimension112="c01c4c16-c990-11f1-bc3b-e7f4af19bbfb" data-action="Deal Block" data-label="Glycerin Max (Women's)" data-dimension48="Glycerin Max (Women's)" data-dimension25="$149">Glycerin Max (Women's): was $199 now $149</a></strong><br />The original Glycerin Max is not just $50 cheaper than the Glycerin Max 2 thanks to this deal, I also think it's better than the latest model because it's a bit lighter. This is the most cushioned model in the Brooks' line-up, and perfect for anyone who loves a comfortable running shoe.<a class="view-deal button" href="https://www.amazon.com/Brooks-Womens-Glycerin-Peacoat-Ribbon/dp/B0D3B6HXJ7" target="_blank" rel="nofollow" data-dimension112="c01c4c16-c990-11f1-bc3b-e7f4af19bbfb" data-action="Deal Block" data-label="Glycerin Max (Women's)" data-dimension48="Glycerin Max (Women's)" data-dimension25="$149">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4c8e-c990-11f1-9fdd-93c65e5a479e" data-action="Deal Block" data-label="Hyperion Elite 5" data-dimension48="Hyperion Elite 5" data-dimension25="$149" href="https://www.amazon.com/dp/B0F4NG15WR?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:980px;"><p class="vanilla-image-block" style="padding-top:58.67%;"><img id="ZsxwPp8UrjYaq3Tu7V3wud" name="Brooks Hyperion Elite 5" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZsxwPp8UrjYaq3Tu7V3wud-1920-80.png" mos="" align="middle" fullscreen="" width="980" height="575" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>When it comes to running fast, carbon plate racers are the shoe to go for, but they're normally prohibitively expensive. Thanks to this $75 saving the Brooks Hyperion Elite 5 is under $200 in the Amazon sale. It's still not exactly cheap, but if you have PRs in mind, it will help get you there with its lightweight, propulsive design.<a class="view-deal button" href="https://www.amazon.com/dp/B0F4NG15WR?" target="_blank" rel="nofollow" data-dimension112="c01c4c8e-c990-11f1-9fdd-93c65e5a479e" data-action="Deal Block" data-label="Hyperion Elite 5" data-dimension48="Hyperion Elite 5" data-dimension25="$149">View Deal</a></p></div><h3 class="article-body__section" id="section-best-hoka-deals"><span>Best Hoka Deals</span></h3><div class="product"><a data-dimension112="c01c4d88-c990-11f1-b97f-91ade45f2509" data-action="Deal Block" data-label="Arahi 8 (Women's)" data-dimension48="Arahi 8 (Women's)" data-dimension25="$120" href="https://www.hoka.com/en/us/womens-everyday-running-shoes/arahi-8/1168691.html?dwvar_1168691_color=FSTS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1932px;"><p class="vanilla-image-block" style="padding-top:81.11%;"><img id="EUf3iisgBNqSoAfRcsnYMU" name="Arahi 8" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/EUf3iisgBNqSoAfRcsnYMU-1920-80.jpg" mos="" align="middle" fullscreen="" width="1932" height="1567" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/womens-everyday-running-shoes/arahi-8/1168691.html?dwvar_1168691_color=FSTS" target="_blank" rel="nofollow" data-dimension112="c01c4d88-c990-11f1-b97f-91ade45f2509" data-action="Deal Block" data-label="Arahi 8 (Women's)" data-dimension48="Arahi 8 (Women's)" data-dimension25="$120">Arahi 8 (Women's): was $150 now $120</a></strong><br />The Arahi 8 is the stable counterpart to the Clifton 10, offering extra support for runners who overpronate along with Hoka's familiar smooth, cushioned ride. It'd great for neutral runners, and the newer Arahi 9 is very similar in all respects, so the older model is definitely better value in the sale.<a class="view-deal button" href="https://www.hoka.com/en/us/womens-everyday-running-shoes/arahi-8/1168691.html?dwvar_1168691_color=FSTS" target="_blank" rel="nofollow" data-dimension112="c01c4d88-c990-11f1-b97f-91ade45f2509" data-action="Deal Block" data-label="Arahi 8 (Women's)" data-dimension48="Arahi 8 (Women's)" data-dimension25="$120">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4e00-c990-11f1-bb6f-9db9b30dcbde" data-action="Deal Block" data-label="Challenger 8 (Men's)" data-dimension48="Challenger 8 (Men's)" data-dimension25="$124" href="https://www.hoka.com/en/us/mens-trail/challenger-8/1168716.html?dwvar_1168716_color=WNH" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1932px;"><p class="vanilla-image-block" style="padding-top:81.11%;"><img id="3XcNm4G4Mycujx4hDGuqPU" name="Challenger" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3XcNm4G4Mycujx4hDGuqPU-1920-80.jpg" mos="" align="middle" fullscreen="" width="1932" height="1567" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/mens-trail/challenger-8/1168716.html?dwvar_1168716_color=WNH" target="_blank" rel="nofollow" data-dimension112="c01c4e00-c990-11f1-bb6f-9db9b30dcbde" data-action="Deal Block" data-label="Challenger 8 (Men's)" data-dimension48="Challenger 8 (Men's)" data-dimension25="$124">Challenger 8 (Men's): was $155 now $124</a></strong><br />The Hoka Challenger 8 is great for its versatility, because it grips well on both roads and light trails, and is comfortable for runs of any distance. It's also a great hiking shoe and can be worn before, during and after your runs. <a class="view-deal button" href="https://www.hoka.com/en/us/mens-trail/challenger-8/1168716.html?dwvar_1168716_color=WNH" target="_blank" rel="nofollow" data-dimension112="c01c4e00-c990-11f1-bb6f-9db9b30dcbde" data-action="Deal Block" data-label="Challenger 8 (Men's)" data-dimension48="Challenger 8 (Men's)" data-dimension25="$124">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4e78-c990-11f1-b993-d79635ad2a4a" data-action="Deal Block" data-label="Clifton 10 (Men's)" data-dimension48="Clifton 10 (Men's)" data-dimension25="$124" href="https://www.hoka.com/en/us/mens-everyday-running-gear/clifton-10/1162030.html?dwvar_1162030_color=WKY" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1932px;"><p class="vanilla-image-block" style="padding-top:81.11%;"><img id="pTkmatx4tcURfCFTcWdCu9" name="Clifton 10" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pTkmatx4tcURfCFTcWdCu9-1920-80.jpg" mos="" align="middle" fullscreen="" width="1932" height="1567" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/mens-everyday-running-gear/clifton-10/1162030.html?dwvar_1162030_color=WKY" target="_blank" rel="nofollow" data-dimension112="c01c4e78-c990-11f1-b993-d79635ad2a4a" data-action="Deal Block" data-label="Clifton 10 (Men's)" data-dimension48="Clifton 10 (Men's)" data-dimension25="$124">Clifton 10 (Men's): was $155 now $124</a></strong><br />The Clifton is the most popular Hoka running shoe for a reason. It’s the perfect place to start with the brand, offering a smooth, comfortable ride that will suit runners of all levels well. It also offers better value than Hoka's rivals, like the Bondi 9.<a class="view-deal button" href="https://www.hoka.com/en/us/mens-everyday-running-gear/clifton-10/1162030.html?dwvar_1162030_color=WKY" target="_blank" rel="nofollow" data-dimension112="c01c4e78-c990-11f1-b993-d79635ad2a4a" data-action="Deal Block" data-label="Clifton 10 (Men's)" data-dimension48="Clifton 10 (Men's)" data-dimension25="$124">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4efa-c990-11f1-a8a0-db7454b62b4b" data-action="Deal Block" data-label="Clifton 9 GTX (Women's)" data-dimension48="Clifton 9 GTX (Women's)" data-dimension25="$132" href="https://www.hoka.com/en/us/womens-everyday-running-shoes/clifton-9-gtx/1141490.html?dwvar_1141490_color=BNDR" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1932px;"><p class="vanilla-image-block" style="padding-top:81.11%;"><img id="RRxC8fKVUmNBdxEfjnVQFf" name="Clifton 9 GTX (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/RRxC8fKVUmNBdxEfjnVQFf-1920-80.webp" mos="" align="middle" fullscreen="" width="1932" height="1567" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/womens-everyday-running-shoes/clifton-9-gtx/1141490.html?dwvar_1141490_color=BNDR" target="_blank" rel="nofollow" data-dimension112="c01c4efa-c990-11f1-a8a0-db7454b62b4b" data-action="Deal Block" data-label="Clifton 9 GTX (Women's)" data-dimension48="Clifton 9 GTX (Women's)" data-dimension25="$132">Clifton 9 GTX (Women's): was $165 now $132</a></strong><br />The <a href="https://www.tomsguide.com/reviews/hoka-clifton-9">Hoka Clifton 9</a> is a cushioned, everyday running shoe that’ll work well for beginners and more experienced runners alike. It’s not the fanciest or the fastest shoe around, but it’s reliably comfortable, whether you’re training for a marathon or using this shoe for your walking workouts. The GTX version adds weatherproofing, so you'll get more out of your walks and runs, rain or shine.<a class="view-deal button" href="https://www.hoka.com/en/us/womens-everyday-running-shoes/clifton-9-gtx/1141490.html?dwvar_1141490_color=BNDR" target="_blank" rel="nofollow" data-dimension112="c01c4efa-c990-11f1-a8a0-db7454b62b4b" data-action="Deal Block" data-label="Clifton 9 GTX (Women's)" data-dimension48="Clifton 9 GTX (Women's)" data-dimension25="$132">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4f72-c990-11f1-93d2-330f9e5c8d04" data-action="Deal Block" data-label="Mafate Speed 2 (Unisex)" data-dimension48="Mafate Speed 2 (Unisex)" data-dimension25="$136" href="https://www.hoka.com/en/us/all-gender-footwear/mafate-speed-2/1126851.html?dwvar_1126851_color=BWHT" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1932px;"><p class="vanilla-image-block" style="padding-top:81.11%;"><img id="9K5YzNyJZBd44NsmvkK3zX" name="Mafate Speed 2" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/9K5YzNyJZBd44NsmvkK3zX-1920-80.jpg" mos="" align="middle" fullscreen="" width="1932" height="1567" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/all-gender-footwear/mafate-speed-2/1126851.html?dwvar_1126851_color=BWHT" target="_blank" rel="nofollow" data-dimension112="c01c4f72-c990-11f1-93d2-330f9e5c8d04" data-action="Deal Block" data-label="Mafate Speed 2 (Unisex)" data-dimension48="Mafate Speed 2 (Unisex)" data-dimension25="$136">Mafate Speed 2 (Unisex): was $170 now $136</a></strong><br />Right now, the Hoka Mafate 2 is 20% off. It provides extra cushioning and protection for long, tough, technical trails—ideal for ultra-distance runs. It’s a bit heavier than the Speedgoat 6 but is designed for comfort mile after mile. <a class="view-deal button" href="https://www.hoka.com/en/us/all-gender-footwear/mafate-speed-2/1126851.html?dwvar_1126851_color=BWHT" target="_blank" rel="nofollow" data-dimension112="c01c4f72-c990-11f1-93d2-330f9e5c8d04" data-action="Deal Block" data-label="Mafate Speed 2 (Unisex)" data-dimension48="Mafate Speed 2 (Unisex)" data-dimension25="$136">View Deal</a></p></div><h3 class="article-body__section" id="section-best-nike-deals"><span>Best Nike Deals</span></h3><div class="product"><a data-dimension112="c01c5062-c990-11f1-b512-b716997cca4f" data-action="Deal Block" data-label="Air Max Alpha Trainer 6 Workout Shoes (Men's)" data-dimension48="Air Max Alpha Trainer 6 Workout Shoes (Men's)" data-dimension25="$79" href="https://www.amazon.com/dp/B0FQN1FHK9?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1618px;"><p class="vanilla-image-block" style="padding-top:45.67%;"><img id="pk5XnTCWLaWiYRnXrqNnt5" name="Air Max Alpha Trainer 6 Workout Shoes (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pk5XnTCWLaWiYRnXrqNnt5-1920-80.jpg" mos="" align="middle" fullscreen="" width="1618" height="739" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0FQN1FHK9?" target="_blank" rel="nofollow" data-dimension112="c01c5062-c990-11f1-b512-b716997cca4f" data-action="Deal Block" data-label="Air Max Alpha Trainer 6 Workout Shoes (Men's)" data-dimension48="Air Max Alpha Trainer 6 Workout Shoes (Men's)" data-dimension25="$79">Air Max Alpha Trainer 6 Workout Shoes (Men's): was $100 now $79</a></strong><br />Super cushioned and perfect for all kinds of workouts, these Nike shoes have dropped in price. They're designed to be stable and flexible and have a rubber wrap to keep your feet in place. Their simple style means they go with any kind of workout gear, too.<a class="view-deal button" href="https://www.amazon.com/dp/B0FQN1FHK9?" target="_blank" rel="nofollow" data-dimension112="c01c5062-c990-11f1-b512-b716997cca4f" data-action="Deal Block" data-label="Air Max Alpha Trainer 6 Workout Shoes (Men's)" data-dimension48="Air Max Alpha Trainer 6 Workout Shoes (Men's)" data-dimension25="$79">View Deal</a></p></div><div class="product"><a data-dimension112="c01c50da-c990-11f1-a981-71bebbd4a682" data-action="Deal Block" data-label="Pegasus 41 Running Shoes (Women's)" data-dimension48="Pegasus 41 Running Shoes (Women's)" data-dimension25="$99" href="https://www.amazon.com/dp/B0F2G75S6N?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:44.60%;"><img id="8rtJszfW7dGEJYJc4He9CN" name="81O2j-efNTL._AC_SX695_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/8rtJszfW7dGEJYJc4He9CN-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="310" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0F2G75S6N?" target="_blank" rel="nofollow" data-dimension112="c01c50da-c990-11f1-a981-71bebbd4a682" data-action="Deal Block" data-label="Pegasus 41 Running Shoes (Women's)" data-dimension48="Pegasus 41 Running Shoes (Women's)" data-dimension25="$99">Pegasus 41 Running Shoes (Women's): was $140 now $99</a></strong><br />The Pegasus 41 is Nike's popular daily trainer, and the 41st version of the shoe is our favorite yet. The new ReactX midsole and higher stack on the Pegasus 41 give it a softer ride than its predecessors, but it’s not so squishy underfoot as to be unstable in any way. It’s a balanced midsole that is comfortable for easy and long runs, but has a little bounce to it when you want to up the pace. Read our full <a href="https://www.tomsguide.com/wellness/running/i-ran-35-miles-in-the-nike-pegasus-41-and-its-my-favorite-pegasus-in-years">Nike Pegasus 41 review</a> here to find out more.<a class="view-deal button" href="https://www.amazon.com/dp/B0F2G75S6N?" target="_blank" rel="nofollow" data-dimension112="c01c50da-c990-11f1-a981-71bebbd4a682" data-action="Deal Block" data-label="Pegasus 41 Running Shoes (Women's)" data-dimension48="Pegasus 41 Running Shoes (Women's)" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="c01c515c-c990-11f1-98a6-33fcfc026737" data-action="Deal Block" data-label="Vomero 18 Running Shoes (Women's)" data-dimension48="Vomero 18 Running Shoes (Women's)" data-dimension25="$121" href="https://www.amazon.com/dp/B0F2G9VV4R?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:44.46%;"><img id="on8DUvsokY6RbJszwfXseQ" name="Vomero" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/on8DUvsokY6RbJszwfXseQ-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="309" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0F2G9VV4R?" target="_blank" rel="nofollow" data-dimension112="c01c515c-c990-11f1-98a6-33fcfc026737" data-action="Deal Block" data-label="Vomero 18 Running Shoes (Women's)" data-dimension48="Vomero 18 Running Shoes (Women's)" data-dimension25="$121">Vomero 18 Running Shoes (Women's): was $150 now $121</a></strong><br />The <a href="https://www.tomsguide.com/wellness/running/nike-vomero-18-review">Nike Vomero 18</a> is a max-cushioned cruiser that's ideal for protecting the body on long and easy runs. It's plush, comfortable and stable. The shoe is pretty heavy, but if you're looking for plush, sink-in comfort, this one ticks that box. <a class="view-deal button" href="https://www.amazon.com/dp/B0F2G9VV4R?" target="_blank" rel="nofollow" data-dimension112="c01c515c-c990-11f1-98a6-33fcfc026737" data-action="Deal Block" data-label="Vomero 18 Running Shoes (Women's)" data-dimension48="Vomero 18 Running Shoes (Women's)" data-dimension25="$121">View Deal</a></p></div><h3 class="article-body__section" id="section-best-saucony-deals"><span>Best Saucony Deals</span></h3><div class="product"><a data-dimension112="c01c524c-c990-11f1-8ae8-7f763e5ec426" data-action="Deal Block" data-label="Cohesion 14 Shoes (Women's)" data-dimension48="Cohesion 14 Shoes (Women's)" data-dimension25="$49" href="https://www.amazon.com/dp/B08CGR4YKG?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:58.99%;"><img id="pdjLV6pX6UWTGkcfsqaSE3" name="Cohesion 14 Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pdjLV6pX6UWTGkcfsqaSE3-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="410" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B08CGR4YKG?" target="_blank" rel="nofollow" data-dimension112="c01c524c-c990-11f1-8ae8-7f763e5ec426" data-action="Deal Block" data-label="Cohesion 14 Shoes (Women's)" data-dimension48="Cohesion 14 Shoes (Women's)" data-dimension25="$49">Cohesion 14 Shoes (Women's): was $75 now $49</a></strong><br />The Saucony Cohesion 14 were already budget-friendly at $75, but now you can get a pair for even less. Shoppers on Amazon love these shoes for their comfortable and supportive design, earning these a 4.1-star rating.<a class="view-deal button" href="https://www.amazon.com/dp/B08CGR4YKG?" target="_blank" rel="nofollow" data-dimension112="c01c524c-c990-11f1-8ae8-7f763e5ec426" data-action="Deal Block" data-label="Cohesion 14 Shoes (Women's)" data-dimension48="Cohesion 14 Shoes (Women's)" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="c01c52ce-c990-11f1-8d27-a3101f90107b" data-action="Deal Block" data-label="Tide 2 Trainer (Men's)" data-dimension48="Tide 2 Trainer (Men's)" data-dimension25="$65" href="https://www.amazon.com/dp/B0D31XXWHZ?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1200px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="gPCzUDufYEii6Von4ywQm" name="image" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gPCzUDufYEii6Von4ywQm-1920-80.png" mos="" align="middle" fullscreen="" width="1200" height="1200" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0D31XXWHZ?" target="_blank" rel="nofollow" data-dimension112="c01c52ce-c990-11f1-8d27-a3101f90107b" data-action="Deal Block" data-label="Tide 2 Trainer (Men's)" data-dimension48="Tide 2 Trainer (Men's)" data-dimension25="$65">Tide 2 Trainer (Men's): was $100 now $65</a></strong><br />The Tide 2 is all about comfort for your everyday. It has soft, springy foam to make every step feel cushioned, a flexible plate to give you a little bounce and move with ease, <em>and</em> a breathable mesh upper to keep your feet cool. Basically, it’s perfect for walking, running errands, or just being on your feet all day without feeling sore.<a class="view-deal button" href="https://www.amazon.com/dp/B0D31XXWHZ?" target="_blank" rel="nofollow" data-dimension112="c01c52ce-c990-11f1-8d27-a3101f90107b" data-action="Deal Block" data-label="Tide 2 Trainer (Men's)" data-dimension48="Tide 2 Trainer (Men's)" data-dimension25="$65">View Deal</a></p></div><div class="product star-deal"><a data-dimension112="440e3b84-c99a-11f1-a464-f3c4efe14e10" data-action="Star Deal Block" data-label="Hurricane 24 (Men's)" data-dimension48="Hurricane 24 (Men's)" data-dimension25="$73" href="https://www.amazon.com/Saucony-Hurricane-Sneaker-Black-Shadow/dp/B0D31XQL4H" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1498px;"><p class="vanilla-image-block" style="padding-top:46.40%;"><img id="vxf7UD5T2Am7guVzFoFcZ4" name="Saucony Hurricane 24 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4-1920-80.jpg" mos="" align="middle" fullscreen="" width="1498" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Saucony-Hurricane-Sneaker-Black-Shadow/dp/B0D31XQL4H" target="_blank" rel="nofollow" data-dimension112="440e3b84-c99a-11f1-a464-f3c4efe14e10" data-action="Star Deal Block" data-label="Hurricane 24 (Men's)" data-dimension48="Hurricane 24 (Men's)" data-dimension25="$73">Hurricane 24 (Men's): was $82 now $73</a></strong><br />Running with the <a href="https://www.tomsguide.com/wellness/running/saucony-hurricane-24-review">Saucony Hurricane 24 </a>is like running on clouds. They use PWRRUN+ foam, which cushions your feet while still feeling springy. With a wide base and rocker design, it offers a stable and comfortable ride for longer or easy runs. The breathable mesh upper fits securely without being tight. The Hurricane 25 have replaced these shoes and they're currently <a href="https://www.amazon.com/Saucony-Mens-Hurricane-Sneaker-Iceberg/dp/B0DJWP4QHZ" target="_blank" rel="nofollow">on sale for $87</a>, but the 24 are the real bargain. <a class="view-deal button" href="https://www.amazon.com/Saucony-Hurricane-Sneaker-Black-Shadow/dp/B0D31XQL4H" target="_blank" rel="nofollow" data-dimension112="440e3b84-c99a-11f1-a464-f3c4efe14e10" data-action="Star Deal Block" data-label="Hurricane 24 (Men's)" data-dimension48="Hurricane 24 (Men's)" data-dimension25="$73">View Deal</a></p></div><div class="product"><a data-dimension112="c01c5346-c990-11f1-acc4-19b0a9479b2b" data-action="Deal Block" data-label="Ride 18 (Men's)" data-dimension48="Ride 18 (Men's)" data-dimension25="$81" href="https://www.amazon.com/Saucony-Mens-Sneaker-BLACK-WHITE/dp/B0D31WZWT8" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1542px;"><p class="vanilla-image-block" style="padding-top:45.07%;"><img id="NmXRUrbSqDWhK8xTzQF7bf" name="Ride 18 (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/NmXRUrbSqDWhK8xTzQF7bf-1920-80.jpg" mos="" align="middle" fullscreen="" width="1542" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Saucony-Mens-Sneaker-BLACK-WHITE/dp/B0D31WZWT8" target="_blank" rel="nofollow" data-dimension112="c01c5346-c990-11f1-acc4-19b0a9479b2b" data-action="Deal Block" data-label="Ride 18 (Men's)" data-dimension48="Ride 18 (Men's)" data-dimension25="$81">Ride 18 (Men's): was $145 now $81</a></strong><br />Comfort and support matter, and the <a href="https://www.tomsguide.com/wellness/fitness/i-ran-45-miles-in-the-saucony-ride-18-heres-my-verdict">Saucony Ride 18</a> delivers both. The soft, bouncy PWRRUN Plus foam feels light underfoot, helping to take the pressure off your joints as you build confidence. The stretchy mesh upper moves with your foot while the padded heel reduces rubbing that can cut runs short. Whether you’re lacing up for your first 5K or logging serious mileage, this shoe is a reliable all-rounder.<a class="view-deal button" href="https://www.amazon.com/Saucony-Mens-Sneaker-BLACK-WHITE/dp/B0D31WZWT8" target="_blank" rel="nofollow" data-dimension112="c01c5346-c990-11f1-acc4-19b0a9479b2b" data-action="Deal Block" data-label="Ride 18 (Men's)" data-dimension48="Ride 18 (Men's)" data-dimension25="$81">View Deal</a></p></div><h3 class="article-body__section" id="section-shop-more-deals"><span>Shop More Deals</span></h3><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Sneakers%2C+running+shoes%2C+sandals&amp;brands=Hoka%2CSkechers%2CAsics&amp;view_mode=carousel&amp;widget_title=Top+Deals+Handpicked+by+Our+Editors&amp;widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&amp;bg_color=light_blue" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters {      display: flex;      gap: 12px;      justify-content: center;      flex-wrap: wrap;    }    .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);      display: -webkit-box;      -webkit-line-clamp: 2;      -webkit-box-orient: vertical;      overflow: hidden;    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    .tg-df-container .tg-df-card-cta.tg-df-cta-savings-squad {      background-color: #3c8d0d;    }    .tg-df-card:hover .tg-df-card-cta.tg-df-cta-savings-squad,    .tg-df-card-cta.tg-df-cta-savings-squad:hover {      background-color: #2b6509;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 0;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 0 16px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }            .tg-df-filters {        width: calc(100% + 32px);        margin: 0 -16px;        padding: 0 16px 4px 16px;        display: flex;        justify-content: flex-start;        gap: 8px;        flex-wrap: nowrap;        overflow-x: auto;        -webkit-overflow-scrolling: touch;        scrollbar-width: none;      }      .tg-df-filters::after {        content: "";        display: block;        flex: 0 0 8px;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }            .tg-df-sort-wrapper {        flex: 0 0 max(42%, 130px);        min-width: 0;      }      .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;        -webkit-line-clamp: 3;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        -webkit-line-clamp: 3;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 16px;      text-align: center;      width: 100%;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: #f8fafc;      border-color: #cbd5e1;    }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right {      background-color: rgba(255, 255, 255, 0.4);      border: none;      box-shadow: none;      backdrop-filter: blur(4px);      -webkit-backdrop-filter: blur(4px);    }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right { right: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-right { right: 0; }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left:hover,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);      border: none;    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-carousel-roundels::after {      content: "";      flex: 0 0 32px;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;      transition: font-weight 0.2s;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-label {      font-weight: 700;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;      display: inline-flex;      align-items: center;      justify-content: center;      min-height: 36px;      box-sizing: border-box;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::after {      content: "";      flex: 0 0 32px;    }    .tg-df-grid-wrapper {      position: relative;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card {      flex: 0 0 auto;      width: 100px;      border-radius: 15px;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      border: 2px solid #1e293b;      background: white;      color: #1e293b;      display: flex;      flex-direction: column;      justify-content: center;      align-items: center;      font-weight: 600;      font-size: 14px;      cursor: pointer;      padding: 16px;      text-align: center;      transition: all 0.2s;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card:hover {      background: #1e293b;      color: white;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      -webkit-line-clamp: 2;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {      -webkit-line-clamp: 3;    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.45);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #5aaf0b; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #4a9109; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>          \x3C/div>          \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">      \x3Cdiv class="tg-df-top-bar">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>                \x3Cdiv class="tg-df-settings-wrapper">          \x3Cbutton type="button" class="tg-df-settings-btn" aria-label="Settings" id="tg-df-settings-toggle">            \x3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20">                \x3Cpath d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.73 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .43-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.49-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/>            \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-settings-dropdown-backdrop" id="tg-df-settings-backdrop">\x3C/div>          \x3Cdiv class="tg-df-settings-dropdown" id="tg-df-settings-panel">            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Search Region\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-region-select">                \x3Coption value="auto">🌍 Auto-detect\x3C/option>                \x3Coption value="US">🇺🇸 United States (US)\x3C/option>                \x3Coption value="GB">🇬🇧 United Kingdom (UK)\x3C/option>                \x3Coption value="CA">🇨🇦 Canada (CA)\x3C/option>                \x3Coption value="AU">🇦🇺 Australia (AU)\x3C/option>                \x3Coption value="DE">🇩🇪 Germany (DE)\x3C/option>                \x3Coption value="FR">🇫🇷 France (FR)\x3C/option>                \x3Coption value="IT">🇮🇹 Italy (IT)\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Retailer\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-retailer-select">                \x3Coption value="">All Retailers\x3C/option>                \x3Coption value="Amazon">Amazon\x3C/option>                \x3Coption value="Walmart">Walmart\x3C/option>                \x3Coption value="Best Buy">Best Buy\x3C/option>                \x3Coption value="Target">Target\x3C/option>                \x3Coption value="John Lewis">John Lewis\x3C/option>                \x3Coption value="Currys">Currys\x3C/option>                \x3Coption value="Argos">Argos\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Offer Type\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-offer-type-select">                \x3Coption value="">All Offers\x3C/option>                \x3Coption value="amazon_prime">Amazon Prime\x3C/option>                \x3Coption value="recommended_promo">Recommended Promo\x3C/option>                \x3Coption value="amazon_lightning">Amazon Lightning Deal\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Result Count\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-rows-select">                \x3Coption value="3">3 Items\x3C/option>                \x3Coption value="4">4 Items\x3C/option>                \x3Coption value="6">6 Items\x3C/option>                \x3Coption value="12" selected>12 Items\x3C/option>                \x3Coption value="24">24 Items\x3C/option>                \x3Coption value="48">48 Items\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Deal Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Only show products with active offers or previous prices (was_price)\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-deal-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Editor Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Enable multi-select to copy deals to CMS\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-editor-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">View Mode\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-view-mode-select">                \x3Coption value="auto">Auto Collection\x3C/option>                \x3Coption value="carousel">Carousel\x3C/option>                \x3Coption value="savings_squad">Savings Squad\x3C/option>                \x3Coption value="grid">Grid (Columns)\x3C/option>                \x3Coption value="row">Row (List)\x3C/option>              \x3C/select>            \x3C/div>          \x3C/div>        \x3C/div>      \x3C/div>      \x3Cdiv class="tg-df-filters">        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M9 3L5 6.99h3V14h2V6.99h3L9 3zm7 14.01V10h-2v7.01h-3L15 21l4-3.99h-3z"/>          \x3C/svg>          \x3Cselect class="tg-df-sort-select" aria-label="Sort Deals">            \x3Coption value="date_desc">Newest First\x3C/option>            \x3Coption value="best_match">Sort by: Match\x3C/option>            \x3Coption value="price_asc">Price Low to High\x3C/option>            \x3Coption value="price_desc">Price High to Low\x3C/option>            \x3Coption value="discount_desc">Biggest Discount\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>        \x3C/div>      \x3C/div>    \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();            if (['carousel', 'carousel-compact', 'auto', 'grid', 'row'].includes(this.getViewMode())) { this.loadCarouselSpreadsheet(); }        }        getViewMode() {          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          if (mode === 'carousel' || mode === 'auto' || mode === 'grid' || mode === 'row') {             if (mode === 'carousel') this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container') && mode === 'carousel') {               this.root.classList.add('is-carousel');             } else if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Everything';             if (this.discountFilter && !params.has('min_discount_ratio')) {               this.discountFilter.value = '5';             }          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (params.has('bg_color')) {            const bg = params.get('bg_color');            if (bg === 'white') {              this.root.style.setProperty('background-color', '#ffffff', 'important');            } else if (bg === 'transparent') {              this.root.style.setProperty('background-color', 'transparent', 'important');            } else if (bg === 'light_blue') {              this.root.style.setProperty('background-color', '#E7F0FF', 'important');            }          } else {             this.root.style.removeProperty('background-color');          }                    if (params.has('view_mode')) {            if (this.viewModeSelect) {              this.viewModeSelect.value = params.get('view_mode');            } else {              this.viewModeOverride = params.get('view_mode');            }          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'discount_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            this.searchInput.value = this.currentQuery;          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'discount_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const roundels = this.root.querySelectorAll('.tg-df-carousel-cat.original-hardcoded');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              if (this.getViewMode() === 'savings_squad' && this.autocompleteDropdown && this.airedaleTags && query.length > 0) {                 const matches = this.airedaleTags.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase()).slice(0, 5);                 if (matches.length > 0) {                    this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                    this.autocompleteDropdown.classList.add('active');                 } else {                    this.autocompleteDropdown.classList.remove('active');                 }              } else if (this.autocompleteDropdown) {                 this.autocompleteDropdown.classList.remove('active');              }              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  this.deals = [];                  this.render();                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                this.activeDealTag = null;                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });              this.activeDealTag = null;              this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.fetchDeals(query);              }            });          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = this.viewModeSelect.value === 'savings_squad' ? 'date_desc' : 'discount_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }                async loadCarouselSpreadsheet() {          try {              const parseCSVRow = (str) => {                  let result = [], cur = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (inQuotes) {                          if (char === '"') {                              if (str[i + 1] === '"') { cur += '"'; i++; }                              else { inQuotes = false; }                          } else { cur += char; }                      } else {                          if (char === '"') { inQuotes = true; }                          else if (char === ',') { result.push(cur); cur = ''; }                          else { cur += char; }                      }                  }                  result.push(cur); return result;              };              const parseCSV = (str) => {                  const rows = []; let curRow = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (char === '"') inQuotes = !inQuotes;                      if ((char === '\n' || char === '\r') && !inQuotes) {                          if (char === '\r' && str[i+1] === '\n') i++;                          if (curRow) rows.push(parseCSVRow(curRow));                          curRow = '';                      } else { curRow += char; }                  }                  if (curRow) rows.push(parseCSVRow(curRow));                  return rows;              };              const preloadedCSV = decodeURIComponent(escape(atob("LCwxLDIsMyw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNQ0KUm91bmRlbCB0ZXh0LEFsbCxUVnMsRm9vdHdlYXIsQXBwYXJlbCxNYXR0cmVzZXMsQXBwbGlhbmNlcyxXZWFyYWJsZSB0ZWNoLEhlYWRwaG9uZXMsU21hcnQgSG9tZSxTcGVha2VycyxMYXB0b3BzLFRhYmxldHMsQ29tcHV0aW5nLFBob25lcyxHYW1pbmcsTGVnbw0KUm91bmRlbCBpbWFnZSxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL2FpLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3R2cy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvN2IzYTIyNGIwNzk2M2M2MjdiNmI5MDliZDc4MzM4MzZlMDJmZjgxOS5qcGcud2VicCxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy84NGRhYzVkNDhlZDJkNDQ4NTU5ZWJhNjdhY2U4MzE0Y2M2N2NjZDk0LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vcHJvZHVjdHMvY2Fyb3VzZWwvbWF0dHJlc3Nlcy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvNzY4ZTk3Y2ViMDcxODAxZmFlMjA5MTBkMDgyMGIxNmY3NDdhZjkzOS5qcGcud2VicCxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3dlbGxuZXNzLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL2hlYWRwaG9uZXMuanBnLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzg5NTM1YmVlYmUyMGRiYmQ0YTM0NmQ2ZDZiZGZlOTFkOGE4ODRhMjEuanBnLndlYnAsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9hdWRpby5qcGcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9sYXB0b3BzLmpwZyxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy8yMzk3NTY0ZWQ3YTVmZjk0N2U5YjZiMzBlNTRmNDc0OTRiODQxZjg5LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vcHJvZHVjdHMvY2Fyb3VzZWwvY29tcHV0aW5nLmpwZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3Bob25lcy5wbmcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9nYW1pbmcucG5nLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzRmNmM2MjFjYWMwYmMxYTg1ZDU5M2UzNTk0YmE1YjM0OWVmZmQyOTIuanBnLndlYnANClNlYXJjaCBRdWVyeSxFdmVyeXRoaW5nLFRlbGV2aXNpb25zLCJTbmVha2VycywgcnVubmluZyBzaG9lcywgc2FuZGFscyIsQ2xvdGhpbmcsTWF0dHJlc3NlcyxIb21lIEFwcGxpYW5jZXMsV2VhcmFibGVzICYgRml0bmVzcyBUZWNoLEhlYWRwaG9uZXMsSG9tZSBUZWNoLFNwZWFrZXJzLExhcHRvcHMsVGFibGV0cyxDb21wdXRpbmcsUGhvbmVzLEdhbWluZyxDb25zdHJ1Y3Rpb24gVG95cw0KRGlzY291bnQgQW1vdW50LG1pbiA1JSxtaW4gMTAlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUNClByaWNlIFJhbmdlLCwsLCxtaW4gJDQwMCwsLCxtaW4gJDI1LCxtaW4gJDMwMCwsLG1pbiAkMTAwLCwNCkJyYW5kIFNlbGVjdGlvbiwsLCwsLCwsLCwsLCwsLCwNCkZpbHRlciBidXR0b25zLCwsLCwsLCwsLCwsLCwsLA0KMSxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMNCjIsQW1hem9uIGRlYWxzLFVuZGVyICQxMDAwLDUwJSBvZmYsQWRpZGFzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsNTAlIG9mZixBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscw0KMyxPdmVyICQ0MDAsVW5kZXIgJDUwMCxIb2thLE5pa2UsU2FhdHZhLE5pbmphLDQwJSBvZmYsSkxhYiwsSkJMLERlbGwsLEFzdXMsQXBwbGUsQ29uc29sZXMsU3RhciBXYXJzDQo0LFVuZGVyICQxMDAwLDUwJSBvZmYsU2tlY2hlcnMsVW5kZXIgQXJtb3VyLEhlbGl4LFNoYXJrLEdhcm1pbixBbmtlciBTb3VuZGNvcmUsUmluZyxTb25vcyxBcHBsZSxBcHBsZSxUUC1saW5rLFNhbXN1bmcsQWNjZXNzb3JpZXMsVW5kZXIgJDI1DQo1LFVuZGVyICQ1MDAsTEcsQXNpY3MsQ29sdW1iaWEsRHJlYW1DbG91ZCxLZXVyaWcsQXBwbGUsU29ueSxHb3ZlZSxUcmliaXQsTGVub3ZvLFNhbXN1bmcsRWVybyxHb29nbGUsR2FtZXMsVW5kZXIgJDUwDQo2LDUwJSBvZmYsU2Ftc3VuZyxOaWtlLFBhdGFnb25pYSxOZWN0YXIsRGUnTG9uZ2hpLEFtYXpmaXQsQXBwbGUsS2FzYSBzbWFydCxTb255LEFsaWVud2FyZSxUQ0wsTmV0Z2VhcixNb3Rvcm9sYSxOaW50ZW5kbyxCb3RhbmljYWxzDQo3LEFtYXpvbixIaXNlbnNlLE5ldyBCYWxhbmNlLEFyYyd0ZXJ5eCxUZW1wdXItcGVkaWMsRHlzb24sRml0Yml0LEJlYXRzLFBoaWxpcHMgSHVlLEFua2VyLEFjZXIsT25lUGx1cyxEZWxsLE9uZVBsdXMsU29ueSxEaXNuZXkNCjgsQXBwbGUsVENMLEFkaWRhcyxDYXJoYXJ0dCxCZWFyLEJpc3NlbGwsU2Ftc3VuZyxFYXJmdW4sQmxpbmssQmVhdHMsTVNJLE1pY3Jvc29mdCxBY2VyLE5vdGhpbmcsWGJveCxNYXJ2ZWwNCjksLFNvbnksU2F1Y29ueSxUaGUgTm9ydGggRmFjZSxTaWVuYSxOdXRyaWJ1bGxldCxPdXJhLFNhbXN1bmcsR29vZ2xlIE5lc3QgLE1hcnNoYWxsLFNhbXN1bmcsTGVub3ZvLExlbm92bywsLFBva2Vtb24NCjEwLCxSb2t1LEJpcmtlbnN0b2NrLENSWiBZb2dhLFdpbmtCZWRzLEJsYWNrIGFuZCBEZWNrZXIsUmluZ2Nvbm4sQ01GLEV1ZnksU2Ftc3VuZyxNaWNyb3NvZnQsUmVNYXJrYWJsZSxBbGllbndhcmUsLCwNCjExLCwsQnJvb2tzLFRoZSBHeW0gUGVvcGxlLEJyb29rbHluIGJlZGRpbmcsTmVzcHJlc3NvLCwxTW9yZSxBcmxvLCxSYXplciwsQ29yc2FpciwsLA0KMTIsLCxDcm9jcywsRWlnaHQgU2xlZXAsQ3Vpc2luYXJ0LCxKQkwsLCwsLEhQLCwsDQpOb3RlcywsLCwsLCwsLCwsLCwsLCwNCiwsIlByaW9yaXRpc2UgYmlnZ2VzdCAlLyQgZGlzY291bnQsIFR2cyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiB0aGUgbW9zdCBwb3B1bGFyIGV2ZW4gaWYgdGhleSBhcmUgc3RpbGwgZXhwZW5zaXZlIiwiTm8gcGF0dGVybiB0byBwcmljaW5nL2Rpc2NvdW50LCByZWFkZXJzIG1haW5seSBzaG9wIGJ5IGJyYW5kL3JlY29nbmlzYWJsZSBzaG9lcyIsIk5vIHBhdHRlcm4gdG8gcHJpY2luZy9kaXNjb3VudCwgcmVhZGVycyBtYWlubHkgc2hvcCBieSBicmFuZCIsIkEgbGFiZWwgd2lsbCBkZWZpbml0ZWx5IGhlbHAgaGVyZSBlLmcuIGJlc3QgZm9yIHNpZGUgc2xlZXBlciwgYmVzdCBtZW1vcnkgZm9hbSIsIkFwcGxpYW5jZXMgaXMgYSBiaWcgY2F0ZWdvcnksIGlzIGl0IHBvc3NpYmxlIHRvIHNwbGl0IGludG8ga2l0Y2hlbiBhcHBsaWFuY2VzLCBmbG9vcmNhcmUsIGFpciBoZWFsdGgvY29vbGluZz8gT3Igc2ltaWxhciIsIkZvY3VzIG9uIHZhbHVlIGZvciBtb25leSwgR2FybWlucyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiBwb3B1bGFyIGV2ZW4gdGhvdWdoIHRoZXkgYXJlIHN0aWxsICQ1MDAiLCwsLCxJbmNsdWRlIEtpbmRsZXMsSSB3b3VsZCBpbmNsdWRlIHdpZmkgcm91dGVycyBoZXJlIGluc3RlYWQgb2Ygc21hcnQgaG9tZSxDYW4gd2Ugc3VyZmFjZSBwaG9uZSBwcm92aWRlciBkZWFscz8gVC1tb2JpbGUgYW5kIHZlcml6b24gd291bGQgbWFrZSBhIGxvdCBtb3JlIG1vbmV5IHRoYW4gQW1hem9uLCwNCiwsaGF2aW5nIGEgJ2Jlc3QgZm9yJyBsYWJlbCB3b3VsZCBiZSBoZWxwZnVsIGUuZy4gYmVzdCBmb3IgYnJpZ2h0IHJvb20sQ2FuIHdlIHN0b3Aga2lkcyBzaG9lcyBmcm9tIHB1bGxpbmcgdGhyb3VnaD8sIldpbGwgdGhpcyBpbmNsdWRlIGFjY2Vzc29yaWVzIGUuZy4gY2FwcywgYmFncywgaWYgc28gbWFrZSBzdXJlIHRoZXNlIGFyZSBtaXhlZCB0aHJvdWdob3V0IGNsb3RoaW5nIGRlYWxzIixXaWxsIHRoaXMgaW5jbHVkZSB0b3BwZXJzIGFuZCBwaWxsb3dzPyBTZWVpbmcgbW9yZSBtb21lbnR1bSB3aXRoIHRoaXMgY2F0ZWdvcnkgcmVjZW50bHkgc28gYSBiZWRkaW5nIHRhYiBtaWdodCB3b3JrLCwiTmVlZCB0byBtYWtlIHN1cmUgYmFuZHMsIHNjcmVlbiBwcm90ZWN0b3JzIGV0Yy4gZG9uJ3QgcHVsbCBpbnRvIGhlcmUiLCwsLCwsLCwsDQosLCJQcmlvcml0aXNlIDY1JycgYW5kIDU1JyBpbmNoIFRWcywgdGhlbiBiaWdnZXIgc2NyZWVucyBiZWZvcmUgdGhlIHNtYWxsZXIgc2l6ZXMiLCwsUXVlZW4gaXMgdGhlIG1vc3QgcG9wdWxhciBzaXplIGluIHRoZSBVUyAtIHByaW9yaXRpc2UgZGVhbHMgZm9yIHRoaXMgc2l6ZSwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpDYXRlZ29yaWVzIHRvIGNvbnNpZGVyLCxQcm9kdWN0cyBpbmNsdWRlZCwsLCwsLCwsLCwsLCwsDQpVbmRlciAkNTA/LCxBaXIgdGFncywsLCwsLCwsLCwsLCwsDQosLFBvcnRhYmxlIGNoYXJnZXJzL3dpcmVsZXNzIGNoYXJnZXJzLCwsLCwsLCwsLCwsLCwNCiwsIldhdGVyIGJvdHRsZXMgKHN0YW5sZXlzLCBPd2FsYSwgSHlkcm8gZmxhc2ssIFlldGkpIiwsLCwsLCwsLCwsLCwsDQosLEhhbmQgaGVsZCBmYW5zLCwsLCwsLCwsLCwsLCwNCiwsLCwsLCwsLCwsLCwsLCwNCmhvbWUgb2ZmaWNlLCxvZmZpY2UgY2hhaXJzLCwsLCwsLCwsLCwsLCwNCiwsc3RhbmRpbmcgZGVza3MsLCwsLCwsLCwsLCwsLA0KLCxtb25pdG9ycywsLCwsLCwsLCwsLCwsDQosLEtleWJvYXJkcywsLCwsLCwsLCwsLCwsDQosLGRvY2tpbmcgc3RhdGlvbiwsLCwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpHYW1pbmcsLENvbnNvbGVzLCwsLCwsLCwsLCwsLCwNCiwsQWNjZXNzb3JpZXMsLCwsLCwsLCwsLCwsLA0KLCxHYW1lcywsLCwsLCwsLCwsLCwsDQosLENvdWxkIGluY2x1ZGUgTGVnbz8sLCwsLCwsLCwsLCwsLA==")));              const text = preloadedCSV;              const parsed = parseCSV(text);                            const rowsByName = {};              let filterStart = -1;              parsed.forEach((rc, i) => {                 if (rc && rc.length > 0 && rc[0]) rowsByName[rc[0]] = rc;                 if (rc && rc.length > 0 && rc[0] === 'Filter buttons') filterStart = i;              });                            const cols = [];              if(rowsByName['Roundel text']) {                const headerRow = rowsByName['Roundel text'];                for(let col = 1; col < headerRow.length; col++) {                   let label = headerRow[col];                   if (!label) continue;                                      let q = rowsByName['Search Query'] && rowsByName['Search Query'][col] ? rowsByName['Search Query'][col] : '';                   let img = rowsByName['Roundel image'] && rowsByName['Roundel image'][col] ? rowsByName['Roundel image'][col] : '';                   let ds = rowsByName['Discount Amount'] && rowsByName['Discount Amount'][col] ? rowsByName['Discount Amount'][col] : '';                   let pr = rowsByName['Price Range'] && rowsByName['Price Range'][col] ? rowsByName['Price Range'][col] : '';                   let rt = rowsByName['Retailer'] && rowsByName['Retailer'][col] ? rowsByName['Retailer'][col] : '';                   let ot = rowsByName['Offer Type'] && rowsByName['Offer Type'][col] ? rowsByName['Offer Type'][col] : '';                                      let filters = [];                   if(filterStart > 0) {                     for(let r = filterStart + 1; r < parsed.length; r++) {                         if(!parsed[r] || parsed[r][0] === 'Notes' || parsed[r][0] === 'Categories to consider') break;                         let f = parsed[r][col];                         if(f) filters.push(f);                     }                   }                   cols.push({ label, img, q, ds, pr, rt, ot, filters });                }              }              this.carouselData = cols;              if (this.carouselData && this.carouselData.length > 0) {                 const isMatched = this.carouselData.some(c => c.q === this.currentQuery || c.label === this.currentQuery);                 if (!isMatched) {                    const first = this.carouselData[0];                    this.currentQuery = first.q || first.label;                    if (this.priceFilter) this.priceFilter.value = 'all';                    if (this.customPriceMin) this.customPriceMin.value = '';                    if (this.customPriceMax) this.customPriceMax.value = '';                    let dPr = first.pr || 'all';                    if (typeof dPr === 'string' && dPr !== 'all') {                       let prLower = dPr.toLowerCase();                       if (prLower.includes('min') || prLower.includes('over')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else if (prLower.includes('max') || prLower.includes('under')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       }                    }                    let dAm = '0';                    if(first.ds && typeof first.ds === 'string') {                       let m = first.ds.match(/(\d+)/);                       if(m) dAm = m[1];                    }                    if (this.discountFilter) this.discountFilter.value = dAm;                    if (this.offerTypeSelect) this.offerTypeSelect.value = first.ot || '';                    if (this.retailerSelect) this.retailerSelect.value = first.rt || '';                    this.selectedBrands = [];                    if (this.brandDropdown) {                        const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                        chks.forEach(chk => chk.checked = false);                    }                    if (this.searchInput) this.searchInput.value = this.currentQuery;                 }              }              this.renderCarouselUI();          } catch(e){ console.warn(e); }        }                renderCarouselUI() {           const roundelWrapper = this.root.querySelector('.tg-df-carousel-roundels');           if(!roundelWrapper || !this.carouselData) return;                      let html = '';           this.carouselData.forEach(r => {              const q = r.q || r.label;              const isActive = (this.currentQuery === q || this.currentQuery === r.label) ? 'active' : '';              const imgHtml = r.img ? `\x3Cimg src="${r.img}" alt="${r.label}" />` : `\x3Csvg width="32" height="32" fill="#1F69FF" viewBox="0 0 24 24">\x3Cpath d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/>\x3C/svg>`;              html += `                \x3Cdiv class="tg-df-roundel tg-df-carousel-cat ${isActive}" data-label="${this.escapeHTML(r.label)}">                  \x3Cdiv class="tg-df-roundel-img-box">${imgHtml}\x3C/div>                  \x3Cspan class="tg-df-roundel-label">${this.escapeHTML(r.label)}\x3C/span>                \x3C/div>              `;           });           roundelWrapper.innerHTML = html;                      // Rebind clicks           const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');           roundels.forEach(rNode => {             rNode.addEventListener('click', () => {                const r = this.carouselData.find(c => c.label === rNode.getAttribute('data-label'));                 if(!r) return;                                  if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: r.label,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = r.q || r.label;                const labelTitle = this.root.querySelector('#tg-df-carousel-title-label');                if (labelTitle) labelTitle.textContent = 'Best ' + this.currentQuery;                if (this.priceFilter) this.priceFilter.value = 'all';                if (this.customPriceMin) this.customPriceMin.value = '';                if (this.customPriceMax) this.customPriceMax.value = '';                let dPr = r.pr || 'all';                if (typeof dPr === 'string' && dPr !== 'all') {                   let prLower = dPr.toLowerCase();                   if (prLower.includes('min') || prLower.includes('over')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMin) this.customPriceMin.value = m[1];                   } else if (prLower.includes('max') || prLower.includes('under')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMax) this.customPriceMax.value = m[1];                   }                }                                let discountAmount = '0';                if(r.ds && typeof r.ds === 'string') {                   let m = r.ds.match(/(\d+)/);                   if(m) discountAmount = m[1];                }                if (this.discountFilter) this.discountFilter.value = discountAmount;                if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                                // Clear brands                    this.selectedBrands = [];                    if (this.brandDropdown) {                    const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                    chks.forEach(chk => chk.checked = false);                }                                if (this.searchInput) this.searchInput.value = this.currentQuery;                                roundels.forEach(ro => ro.classList.remove('active'));                if (rNode) rNode.classList.add('active');                                this.renderCarouselFilters(r);                this.fetchDeals(this.currentQuery);             });           });                      // Auto-highlight active           const activeR = this.carouselData.find(c => c.q === this.currentQuery || c.label === this.currentQuery);           if(activeR) this.renderCarouselFilters(activeR);        }                renderCarouselFilters(r) {           const filtersWrap = this.root.querySelector('.tg-df-carousel-filters-wrap');           if(!filtersWrap) return;                      let html = `\x3Cbutton class="tg-df-carousel-filter-btn" data-type="all">All\x3C/button>`;                      r.filters.forEach(f => {              let fL = f.toLowerCase();              let icon = '';              let logic = `data-type="custom" data-v="${this.escapeHTML(f)}"`;              if (fL === 'amazon deals' || fL === 'prime deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>`;              } else if (fL === 'lightning deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>`;              } else {                 if (fL.includes('lightning')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-zap">\x3Cpolygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2">\x3C/polygon>\x3C/svg>`;                 } else if (fL.includes('% off')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>`;                 } else if (fL.includes('under') || fL.includes('min ')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>`;                 }                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>${icon} ${this.escapeHTML(f)}\x3C/button>`;              }           });                      filtersWrap.innerHTML = html;                      const btns = filtersWrap.querySelectorAll('button');           btns.forEach(b => {             b.addEventListener('click', () => {                const type = b.getAttribute('data-type');                if (type === 'custom') {                   const v = b.getAttribute('data-v');                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-custom-${(v||'').toLowerCase().replace(/[^a-z0-9]+/g, '-')}`, name: 'Custom Filter', label: v });                }                if (type === 'all') {                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: 'filter-clear-all', name: 'Clear all', label: 'Clear all filters' });                   // reset everything                   btns.forEach(btn => btn.classList.remove('active'));                   b.classList.add('active');                                      // Reset prices                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   if (this.brandDropdown) {                     const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                     chks.forEach(chk => chk.checked = false);                   }                } else {                   const v = b.getAttribute('data-v');                   const fL = v.toLowerCase();                                      let mapRet = ['amazon', 'walmart', 'best buy', 'target', 'john lewis', 'currys', 'argos'];                   const getCategory = (s) => {                      if (s === 'lightning deals' || s === 'amazon deals' || s === 'prime deals') return 'offer';                      if (s.includes('% off')) return 'discount';                      if (s.includes('under') || s.includes('over') || s.includes('min') || s.includes('max')) return 'price';                      if (mapRet.includes(s)) return 'retailer';                      return 'brand';                   };                   const cat = getCategory(fL);                   const wasActive = b.classList.contains('active');                   if (cat !== 'brand') {                      btns.forEach(btn => {                          if (btn === b) return;                          if (btn.getAttribute('data-type') === 'all') return;                          const bV = btn.getAttribute('data-v');                          if (!bV) return;                          if (getCategory(bV.toLowerCase()) === cat) btn.classList.remove('active');                      });                   }                   if (wasActive) b.classList.remove('active');                   else b.classList.add('active');                   let anyActive = Array.from(btns).some(btn => btn !== btns[0] && btn.classList.contains('active'));                   if (!anyActive) {                       btns[0].click();                       return;                   } else {                       btns[0].classList.remove('active');                   }                                      if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   btns.forEach(btn => {                       if (!btn.classList.contains('active') || btn.getAttribute('data-type') === 'all') return;                       const vv = btn.getAttribute('data-v');                       const vl = vv.toLowerCase();                                              if (vl === 'lightning deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_lightning';                       } else if (vl === 'amazon deals' || vl === 'prime deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_prime';                       } else if (vl.includes('% off')) {                          let m = vl.match(/(\d+)%/);                          if (m && this.discountFilter) this.discountFilter.value = m[1];                       } else if (vl.includes('under') || vl.includes('max')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       } else if (vl.includes('min') || vl.includes('over')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else {                          let foundR = mapRet.find(x => x === vl);                          if (foundR) {                             let realR = ['Amazon', 'Walmart', 'Best Buy', 'Target', 'John Lewis', 'Currys', 'Argos'].find(x => x.toLowerCase() === vl);                             if (this.retailerSelect) this.retailerSelect.value = realR;                          } else {                             this.selectedBrands.push(vv);                          }                       }                   });                                      if (this.brandDropdown) {                       const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                       chks.forEach(c => c.checked = this.selectedBrands.includes(c.value));                   }                                      if (r.pr && typeof r.pr === 'string') {                       let prL = r.pr.toLowerCase();                       if (prL.includes('under $')) {                           let m = prL.match(/under \$(\d+)/i);                           if (m && this.customPriceMax && !this.customPriceMax.value) this.customPriceMax.value = m[1];                       }                   }                }                                this.fetchDeals(this.currentQuery);             });           });                      // default to highlighting first           btns[0].classList.add('active');        }async fetchDeals(query, append = false) {          if (!append) {             this.showLoading();             this.deals = [];             this.displayLimit = this.getRowsLimit();          } else {             this.displayLimit += this.getRowsLimit();          }                    try {            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad(append);            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query, append);               } else {                 await this.fetchHawkDeals(query, append);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query, append);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const url = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let dynamicBrandsCounts = {};                    targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                   dynamicBrandsCounts[data.brand] = (dynamicBrandsCounts[data.brand] || 0) + 1;                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || ''                });             });          });                    const airedaleBrandsList = Object.keys(dynamicBrandsCounts).map(b => ({              formatted_value: b,              count: dynamicBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query, append = false) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (append && this.deals.length > 0) {            url.searchParams.append('offset', this.deals.length.toString());          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : (this.getViewMode() === 'savings_squad' ? 'date_desc' : 'discount_desc');          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin-top:8px;">${_div}                ${_div}              ${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)} (${this.airedaleTagCounts[tag] || 0})${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = isSavingsSquadMode ? 'View Deal' : 'Check Price';              if (isSavingsSquadMode) {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                  ${_div}                `;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = `                \x3Cdiv class="tg-df-card-merchant-wrapper">                  \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                ${_div}                \x3Cdiv class="tg-df-card-price-group">                  ${isSavingsSquadMode ? '' : `                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                  `}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description">\x3Cp>${this.escapeHTML(deal.description)}${_p}${_div}` : ''}                      ${_div}                    ${_div}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>${deal.isCheckPrice ? 'Check Price' : 'View Deal'}${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cp style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 12px; line-height: 1.4;">${this.escapeHTML(deal.description)}${_p}` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${priceGroupHtml}                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta ${isSavingsSquadMode ? 'tg-df-cta-savings-squad' : ''}" style="text-decoration: none;">${ctaText}${_a}                  ${_div}                ${_div}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit || ((this.getViewMode() === 'carousel' || this.getViewMode() === 'auto') && displayDeals.length > 0 && displayDeals.length % ((this.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12) === 0)) {            if (this.getViewMode() === 'carousel') {               dealsHtml += `                 \x3Cbutton type="button" class="tg-df-load-more-card tg-df-load-more">                   \x3Csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-bottom: 8px;">\x3Cpath d="M5 12h14">\x3C/path>\x3Cpath d="m12 5 7 7-7 7">\x3C/path>\x3C/svg>                   Load More                 ${_button}               `;            } else {               dealsHtml += `                 \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                   \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer; display: flex; align-items: center;">Load More${_button}                 ${_div}               `;            }          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }                    let gridWrapper = this.grid.parentElement;          if (gridWrapper && gridWrapper.classList.contains('tg-df-grid-wrapper')) {             let rightChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-right');             let leftChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-left');             if (this.getViewMode() === 'carousel') {                 // The observer set up in setupScrollListeners handles visibility.                 if (rightChevron) rightChevron.style.display = 'flex';                 if (leftChevron) leftChevron.style.display = 'none'; // reset correctly             } else {                 if (rightChevron) rightChevron.style.display = 'none';                 if (leftChevron) leftChevron.style.display = 'none';             }          }                    const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', async () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              if (displayDeals.length <= this.displayLimit) {                 loadMoreBtn.innerHTML = `                  <svg class="tg-df-spinner" style="width: 16px; height: 16px; display: inline-block; vertical-align: middle; margin-right: 8px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" d="M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48l2.83-2.83"/></svg>                  Loading...                 `;                 loadMoreBtn.disabled = true;                 await this.fetchDeals(this.currentQuery, true);              } else {                 this.displayLimit += this.getRowsLimit();                 this.render();              }            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            setTimeout(() => {               if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');               document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));            }, 50);          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/running/27-best-running-shoe-deals-for-fall-up-to-50-percent-off-asics-brooks-hoka-and-more</link>
                                                                            <description>
                            <![CDATA[ Top sneaker brands like Hoka, Asics, Brooks and more are hosting huge fall sales. Here are my favorite deals to shop now. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">tiN2K65hZqHj6NAkXwJjCc</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/FzuujwmxEPMBxZv5FpJtSe-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 18 Oct 2026 14:30:00 +0000</pubDate>                                                                                                                                <updated>Mon, 19 Oct 2026 09:11:55 +0000</updated>
                                                                                                                                            <category><![CDATA[Running]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                    <category><![CDATA[Fitness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Olivia Halevy ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/YAg7Fmh9dGKbg3hULBMWiU-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Olivia is a Deals Writer at Tom’s Guide. She loves all things lifestyle, shopping and sourcing the best deals from some of the top brands, retailers and websites around. From fashion and beauty to smart home and tech, she has an eye for finding practical, stylish, and reasonably-priced items that help make life simpler (and a little more aesthetically-pleasing).&amp;nbsp;Olivia has over five years of experience writing lifestyle, commerce, and branded content for &lt;a href=&quot;http://patch.com/&quot;&gt;Patch.com&lt;/a&gt;. She&#039;s covered major shopping holidays like Amazon Prime Day, Black Friday and Cyber Monday. In her free time, she enjoys trying out new exercise classes, binge-watching the latest viral TV shows, cooking, spending time with family and taking long walks with her dog, Gus.&amp;nbsp;&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/FzuujwmxEPMBxZv5FpJtSe-1920-80.jpg">
                                                            <media:credit><![CDATA[Amazon / edited by Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Running shoe deals]]></media:description>                                                            <media:text><![CDATA[Running shoe deals]]></media:text>
                                <media:title type="plain"><![CDATA[Running shoe deals]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/FzuujwmxEPMBxZv5FpJtSe-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>In the market for a new pair of running sneakers? Well, you're in luck! Top brands like New Balance, Asics, Brooks and more are hosting huge sales — and many styles are available to snag right now on Amazon. </p><p>Whether you're hitting the trails, the pavement or the treadmill, there's a pair of sneakers for just about everyone — and select styles are up to 50% off as we speak. So don’t wait! These top deals won’t be around forever. Keep scrolling to shop the best running sneakers for fall. </p><p><strong>Note: </strong>prices vary depending on the size and color you choose; search the different color options available in your size to find the best deals.</p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links </span></h3><ul><li><strong>New Balance: </strong><a href="https://www.amazon.com/stores/page/855D4CDF-ADB7-4BE8-9E26-A085D029E4B5?" target="_blank" rel="nofollow"><strong>up to 50% off</strong></a></li><li><strong>Asics: </strong><a href="https://www.amazon.com/stores/page/848769B1-4C68-4CA5-B2E7-A4480A3FBF59" target="_blank" rel="nofollow"><strong>deals from $54</strong></a></li><li><strong>Adidas: </strong><a href="https://www.amazon.com/stores/adidas/page/5E398A61-45C7-46F9-A6C6-5B4797CC5063?" target="_blank" rel="nofollow"><strong>deals from $39</strong></a></li><li><strong>Brooks: </strong><a href="https://www.amazon.com/stores/Brooks/page/B6834DFA-396F-4E38-98F6-3D2739393271?" target="_blank" rel="nofollow"><strong>up to 40% off</strong></a></li><li><strong>Hoka: </strong><a href="https://www.hoka.com/en/us/sale/" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li><li><strong>Nike: </strong><a href="https://www.amazon.com/stores/page/E9C7C6A6-9A88-4959-A67F-4D44FC67320F" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li><li><strong>Saucony Tide 2 Trainer (Men's): </strong><a href="https://www.amazon.com/dp/B0D31XXWHZ?" target="_blank" rel="nofollow"><strong>was $100 now $65</strong></a></li><li><strong>Asics Glideride Max (Men's): </strong><a href="https://www.amazon.com/ASICS-GLIDERIDE-Running-Monument-Vanilla/dp/B0CT9HG8TB" target="_blank" rel="nofollow"><strong>was $170 now $89</strong></a></li><li><strong>Brooks Hyperion Max 3 (Men's): </strong><a href="https://www.amazon.com/Brooks-Mens-Hyperion-Neutral-Running/dp/B0DM3MTXGK?" target="_blank" rel="nofollow"><strong>was $199 now $108</strong></a></li><li><strong>New Balance FuelCell Trainer V3 (Women's): </strong><a href="https://www.amazon.com/New-Balance-FuelCell-SuperComp-Tangerine/dp/B0F4LZ7VDR" target="_blank" rel="nofollow"><strong>was $264 now $148</strong></a></li></ul><h3 class="article-body__section" id="section-best-new-balance-deals"><span>Best New Balance Deals</span></h3><div class="product"><a data-dimension112="2110009a-cb9d-11f1-8ff2-8d5dc4b13110" data-action="Deal Block" data-label="460 V4 Running Shoe (Women's)" data-dimension48="460 V4 Running Shoe (Women's)" data-dimension25="$48" href="https://www.amazon.com/New-Balance-Womens-Running-Orange/dp/B0CLB2MW44" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:842px;"><p class="vanilla-image-block" style="padding-top:53.09%;"><img id="oogbpG7TLGhF7fbRvzSZTn" name="460 V4 Running Shoe (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/oogbpG7TLGhF7fbRvzSZTn-1920-80.jpg" mos="" align="middle" fullscreen="" width="842" height="447" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-Womens-Running-Orange/dp/B0CLB2MW44" target="_blank" rel="nofollow" data-dimension112="2110009a-cb9d-11f1-8ff2-8d5dc4b13110" data-action="Deal Block" data-label="460 V4 Running Shoe (Women's)" data-dimension48="460 V4 Running Shoe (Women's)" data-dimension25="$48">460 V4 Running Shoe (Women's): was $64 now $48</a></strong><br />Despite their budget-friendly price, the New Balance 460 V4 are packed with soft cushioning and feature a supportive design. Reviewers on Amazon rave about how comfortable these shoes are.<a class="view-deal button" href="https://www.amazon.com/New-Balance-Womens-Running-Orange/dp/B0CLB2MW44" target="_blank" rel="nofollow" data-dimension112="2110009a-cb9d-11f1-8ff2-8d5dc4b13110" data-action="Deal Block" data-label="460 V4 Running Shoe (Women's)" data-dimension48="460 V4 Running Shoe (Women's)" data-dimension25="$48">View Deal</a></p></div><div class="product"><a data-dimension112="c01c42e8-c990-11f1-8eb6-0d66610eaa9e" data-action="Deal Block" data-label="410 V8 Trail Running Shoe (Men's)" data-dimension48="410 V8 Trail Running Shoe (Men's)" data-dimension25="$59" href="https://www.amazon.com/New-Balance-Running-Cayenne-Shadow/dp/B0D2BSMHB2" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:870px;"><p class="vanilla-image-block" style="padding-top:51.38%;"><img id="PnUcM3Fmgz2spyxFtnpAc6" name="image" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/PnUcM3Fmgz2spyxFtnpAc6-1920-80.png" mos="" align="middle" fullscreen="" width="870" height="447" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-Running-Cayenne-Shadow/dp/B0D2BSMHB2" target="_blank" rel="nofollow" data-dimension112="c01c42e8-c990-11f1-8eb6-0d66610eaa9e" data-action="Deal Block" data-label="410 V8 Trail Running Shoe (Men's)" data-dimension48="410 V8 Trail Running Shoe (Men's)" data-dimension25="$59">410 V8 Trail Running Shoe (Men's): was $69 now $59</a></strong><br />The New Balance 410 V8 trainer is a stylish running shoe to hit the trails with! These are kitted out with a soft bio foam in the midsole to keep you comfortable while pounding the trails and have strategic overlays to make sure you get the most out of the pair.<a class="view-deal button" href="https://www.amazon.com/New-Balance-Running-Cayenne-Shadow/dp/B0D2BSMHB2" target="_blank" rel="nofollow" data-dimension112="c01c42e8-c990-11f1-8eb6-0d66610eaa9e" data-action="Deal Block" data-label="410 V8 Trail Running Shoe (Men's)" data-dimension48="410 V8 Trail Running Shoe (Men's)" data-dimension25="$59">View Deal</a></p></div><div class="product"><a data-dimension112="c01c436a-c990-11f1-8a29-331171a080ae" data-action="Deal Block" data-label="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension48="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension25="$108" href="https://www.amazon.com/New-Balance-FuelCell-Running-Afterglow/dp/B0F4LLKZCH" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:880px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="zMXtGm9YKG3arrNYXpTBH" name="New Balance Rebel v5 sq" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zMXtGm9YKG3arrNYXpTBH-1920-80.jpg" mos="" align="middle" fullscreen="" width="880" height="880" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-FuelCell-Running-Afterglow/dp/B0F4LLKZCH" target="_blank" rel="nofollow" data-dimension112="c01c436a-c990-11f1-8a29-331171a080ae" data-action="Deal Block" data-label="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension48="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension25="$108">FuelCell Rebel v5 Running Shoes (Women's): was $144 now $108</a></strong><br />The lightweight <a href="https://www.tomsguide.com/wellness/running/new-balance-rebel-v5-review">New Balance FuelCell Rebel v5</a> is a comfortable and speedy daily trainer that's perfect for those who don't love the feel of max-cushioned shoes, as it has a more grounded feel.<a class="view-deal button" href="https://www.amazon.com/New-Balance-FuelCell-Running-Afterglow/dp/B0F4LLKZCH" target="_blank" rel="nofollow" data-dimension112="c01c436a-c990-11f1-8a29-331171a080ae" data-action="Deal Block" data-label="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension48="FuelCell Rebel v5 Running Shoes (Women's)" data-dimension25="$108">View Deal</a></p></div><div class="product"><a data-dimension112="c01c452c-c990-11f1-8eb9-b985c5a65cfe" data-action="Deal Block" data-label="Ellipse v1 (Men’s)" data-dimension48="Ellipse v1 (Men’s)" data-dimension25="$109" href="https://www.amazon.com/New-Balance-Ellipse-Running-Matter/dp/B0FX3DKKND" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:759px;"><p class="vanilla-image-block" style="padding-top:59.29%;"><img id="77VApTr9xqJVo2amFqMXdP" name="Ellipse v1 (Men’s)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/77VApTr9xqJVo2amFqMXdP-1920-80.jpg" mos="" align="middle" fullscreen="" width="759" height="450" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-Ellipse-Running-Matter/dp/B0FX3DKKND" target="_blank" rel="nofollow" data-dimension112="c01c452c-c990-11f1-8eb9-b985c5a65cfe" data-action="Deal Block" data-label="Ellipse v1 (Men’s)" data-dimension48="Ellipse v1 (Men’s)" data-dimension25="$109">Ellipse v1 (Men’s): was $145 now $109</a></strong><br />This everyday running shoe from New Balance is designed as much for beginners as it is for athletes. Featuring elevated cushioning in the midsole and a breathable engineered-mesh upper, it will work as well for a lunchtime 5K as it will for 5 a.m. marathon training. It's got an 8mm drop and a rockered profile for increased comfort.<a class="view-deal button" href="https://www.amazon.com/New-Balance-Ellipse-Running-Matter/dp/B0FX3DKKND" target="_blank" rel="nofollow" data-dimension112="c01c452c-c990-11f1-8eb9-b985c5a65cfe" data-action="Deal Block" data-label="Ellipse v1 (Men’s)" data-dimension48="Ellipse v1 (Men’s)" data-dimension25="$109">View Deal</a></p></div><div class="product"><a data-dimension112="c01c45d6-c990-11f1-ad42-2133b13010bd" data-action="Deal Block" data-label="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension48="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension25="$138" href="https://www.amazon.com/New-Balance-Running-Metallic-Inkwell/dp/B0CLB6X87W" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:880px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="XwbzzRSwcghwdApXRMQfb5" name="New Balance 1080v14 sq" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/XwbzzRSwcghwdApXRMQfb5-1920-80.jpg" mos="" align="middle" fullscreen="" width="880" height="880" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-Running-Metallic-Inkwell/dp/B0CLB6X87W" target="_blank" rel="nofollow" data-dimension112="c01c45d6-c990-11f1-ad42-2133b13010bd" data-action="Deal Block" data-label="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension48="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension25="$138">Fresh Foam X 1080v14 Running Shoe (Men's): was $164 now $138</a></strong><br />The New Balance 1080v14 is a previous candidate on our list of the <a href="https://www.tomsguide.com/best-picks/best-running-shoes">best running shoes</a>. We gave it a 4-star rating in our <a href="https://www.tomsguide.com/wellness/running/new-balance-fresh-foam-x-1080v14-review">New Balance Fresh Foam X 1080v14 review</a>, saying that this is a cushioned daily trainer that offers a great balance of comfort and weight.<a class="view-deal button" href="https://www.amazon.com/New-Balance-Running-Metallic-Inkwell/dp/B0CLB6X87W" target="_blank" rel="nofollow" data-dimension112="c01c45d6-c990-11f1-ad42-2133b13010bd" data-action="Deal Block" data-label="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension48="Fresh Foam X 1080v14 Running Shoe (Men's)" data-dimension25="$138">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4662-c990-11f1-a56f-f17a5ba42aed" data-action="Deal Block" data-label="FuelCell Supercomp Elite V5 (Women's)" data-dimension48="FuelCell Supercomp Elite V5 (Women's)" data-dimension25="$148" href="https://www.amazon.com/New-Balance-FuelCell-SuperComp-Tangerine/dp/B0F4LZ7VDR" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1267px;"><p class="vanilla-image-block" style="padding-top:54.85%;"><img id="BXfy6JhfauCEwEyTDyxFe3" name="FuelCell Supercomp Elite V5 (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/BXfy6JhfauCEwEyTDyxFe3-1920-80.jpg" mos="" align="middle" fullscreen="" width="1267" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/New-Balance-FuelCell-SuperComp-Tangerine/dp/B0F4LZ7VDR" target="_blank" rel="nofollow" data-dimension112="c01c4662-c990-11f1-a56f-f17a5ba42aed" data-action="Deal Block" data-label="FuelCell Supercomp Elite V5 (Women's)" data-dimension48="FuelCell Supercomp Elite V5 (Women's)" data-dimension25="$148">FuelCell Supercomp Elite V5 (Women's): was $264 now $148</a></strong><br />Our Fitness Editor, Jane McGuire, ran her fastest marathon in the Supercomp Elite V5 — and our Senior Fitness Writer, Nick Harris-Fry loved their lightweight, propulsive design in his <a href="https://www.tomsguide.com/wellness/running/new-balance-sc-elite-v5-review">New Balance FuelCell Supercomp Elite V5 review</a>. Don't sleep on this saving!<a class="view-deal button" href="https://www.amazon.com/New-Balance-FuelCell-SuperComp-Tangerine/dp/B0F4LZ7VDR" target="_blank" rel="nofollow" data-dimension112="c01c4662-c990-11f1-a56f-f17a5ba42aed" data-action="Deal Block" data-label="FuelCell Supercomp Elite V5 (Women's)" data-dimension48="FuelCell Supercomp Elite V5 (Women's)" data-dimension25="$148">View Deal</a></p></div><h3 class="article-body__section" id="section-best-asics-deals"><span>Best Asics Deals</span></h3><div class="product"><a data-dimension112="c01c475c-c990-11f1-b32c-e5dc07b29fb1" data-action="Deal Block" data-label="Gel-Kayano 30 (Women's)" data-dimension48="Gel-Kayano 30 (Women's)" data-dimension25="$69" href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1160px;"><p class="vanilla-image-block" style="padding-top:46.29%;"><img id="iHsvdtLnzyeWEyCZV8HBYe" name="Gel-Kayano 30 (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/iHsvdtLnzyeWEyCZV8HBYe-1920-80.jpg" mos="" align="middle" fullscreen="" width="1160" height="537" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow" data-dimension112="c01c475c-c990-11f1-b32c-e5dc07b29fb1" data-action="Deal Block" data-label="Gel-Kayano 30 (Women's)" data-dimension48="Gel-Kayano 30 (Women's)" data-dimension25="$69">Gel-Kayano 30 (Women's): was $160 now $69</a></strong><br />The Gel Kayano 30 running shoes are an older model, but they're amazingly cheap with 56% off. They're designed to provide advanced stability and soft cushioning for neutral runners and overpronators alike. Our Deals Editor-in-Chief, Louis Ramirez, wrote: "I've been using these shoes for almost two years now. (I loved them so much I bought a second pair months after buying my first pair). I find that they're great for casual runs on the treadmill, HIIT sessions, and long distance running outdoors."<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-Gel-Kayano-Running-Shoes/dp/B0BY3PYZ2D" target="_blank" rel="nofollow" data-dimension112="c01c475c-c990-11f1-b32c-e5dc07b29fb1" data-action="Deal Block" data-label="Gel-Kayano 30 (Women's)" data-dimension48="Gel-Kayano 30 (Women's)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="c01c47d4-c990-11f1-8c7c-91286f932f4d" data-action="Deal Block" data-label="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension48="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension25="$69" href="https://www.amazon.com/ASICS-Gel-Contend-Running-Shoes-Black/dp/B0GGCWVYC7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1156px;"><p class="vanilla-image-block" style="padding-top:45.42%;"><img id="yyx3Rc6DdUotj8NTEwFwLa" name="Gel-Contend 10 Road Running Shoes (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/yyx3Rc6DdUotj8NTEwFwLa-1920-80.jpg" mos="" align="middle" fullscreen="" width="1156" height="525" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Gel-Contend-Running-Shoes-Black/dp/B0GGCWVYC7" target="_blank" rel="nofollow" data-dimension112="c01c47d4-c990-11f1-8c7c-91286f932f4d" data-action="Deal Block" data-label="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension48="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension25="$69">Gel-Contend 10 Road Running Shoes (Men's): was $80 now $69</a></strong><br />The 10th iteration of Asics' budget-friendly road running shoes have dropped in price! They feature Amplifoam+ cushioning to support your runs and have a lightweight and breathable mesh upper.<a class="view-deal button" href="https://www.amazon.com/ASICS-Gel-Contend-Running-Shoes-Black/dp/B0GGCWVYC7" target="_blank" rel="nofollow" data-dimension112="c01c47d4-c990-11f1-8c7c-91286f932f4d" data-action="Deal Block" data-label="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension48="Gel-Contend 10 Road Running Shoes (Men's)" data-dimension25="$69">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4856-c990-11f1-aabf-39c8fd6379ee" data-action="Deal Block" data-label="Women's Novablast 4" data-dimension48="Women's Novablast 4" data-dimension25="$67" href="https://www.amazon.com/ASICS-Womens-NOVABLAST-Running-Expanse/dp/B0CFP3J6RB" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1200px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="wMYSVC2325TPeXMt7TJ9t3" name="Asics Novablast 4" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/wMYSVC2325TPeXMt7TJ9t3-1920-80.jpg" mos="" align="middle" fullscreen="" width="1200" height="1200" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-Womens-NOVABLAST-Running-Expanse/dp/B0CFP3J6RB" target="_blank" rel="nofollow" data-dimension112="c01c4856-c990-11f1-aabf-39c8fd6379ee" data-action="Deal Block" data-label="Women's Novablast 4" data-dimension48="Women's Novablast 4" data-dimension25="$67">Women's Novablast 4: was $140 now $67</a></strong><br />Old but gold. While the Novablast 6 is now available, the Novablast 4 is beloved by the Tom's Guide team — especially our Fitness Editor Jane McGuire, who wrote: "I've run over 100 miles in this shoe, and it's still one I reach for when I'm heading out for a long run."<a class="view-deal button" href="https://www.amazon.com/ASICS-Womens-NOVABLAST-Running-Expanse/dp/B0CFP3J6RB" target="_blank" rel="nofollow" data-dimension112="c01c4856-c990-11f1-aabf-39c8fd6379ee" data-action="Deal Block" data-label="Women's Novablast 4" data-dimension48="Women's Novablast 4" data-dimension25="$67">View Deal</a></p></div><div class="product"><a data-dimension112="c01c48ce-c990-11f1-98e1-1d86104a3678" data-action="Deal Block" data-label="Glideride Max (Men's)" data-dimension48="Glideride Max (Men's)" data-dimension25="$80" href="https://www.amazon.com/ASICS-GLIDERIDE-Running-Monument-Vanilla/dp/B0CT9HG8TB" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1157px;"><p class="vanilla-image-block" style="padding-top:50.91%;"><img id="ur2nzvnBf49fo9rfEakkpK" name="Glideride Max (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ur2nzvnBf49fo9rfEakkpK-1920-80.jpg" mos="" align="middle" fullscreen="" width="1157" height="589" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-GLIDERIDE-Running-Monument-Vanilla/dp/B0CT9HG8TB" target="_blank" rel="nofollow" data-dimension112="c01c48ce-c990-11f1-98e1-1d86104a3678" data-action="Deal Block" data-label="Glideride Max (Men's)" data-dimension48="Glideride Max (Men's)" data-dimension25="$80">Glideride Max (Men's): was $170 now $80</a></strong><br />At 53% off, the Asics Glideride are a steal. These come with GuideSole tech to help you save energy, keeping you going for longer. You also get FF Blast Max cushioning for a lightweight, soft feel.<a class="view-deal button" href="https://www.amazon.com/ASICS-GLIDERIDE-Running-Monument-Vanilla/dp/B0CT9HG8TB" target="_blank" rel="nofollow" data-dimension112="c01c48ce-c990-11f1-98e1-1d86104a3678" data-action="Deal Block" data-label="Glideride Max (Men's)" data-dimension48="Glideride Max (Men's)" data-dimension25="$80">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4950-c990-11f1-90e0-a54efa81122b" data-action="Deal Block" data-label="Sonicblast Road Running Shoes (Men's)" data-dimension48="Sonicblast Road Running Shoes (Men's)" data-dimension25="$94" href="https://www.amazon.com/Asics-SONICBLAST-Running-Winter-Stillwater/dp/B0DPLQ32YV" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1528px;"><p class="vanilla-image-block" style="padding-top:75.00%;"><img id="rD9sdYvxaqtEV2BgyMfTx" name="Sonicblast" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/rD9sdYvxaqtEV2BgyMfTx-1920-80.jpg" mos="" align="middle" fullscreen="" width="1528" height="1146" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Asics-SONICBLAST-Running-Winter-Stillwater/dp/B0DPLQ32YV" target="_blank" rel="nofollow" data-dimension112="c01c4950-c990-11f1-90e0-a54efa81122b" data-action="Deal Block" data-label="Sonicblast Road Running Shoes (Men's)" data-dimension48="Sonicblast Road Running Shoes (Men's)" data-dimension25="$94">Sonicblast Road Running Shoes (Men's): was $180 now $94</a></strong><br />Suited for both fast runs and everyday training, the Asics Sonicblast are super lightweight and propulsive. There's an Astroplate mechanism to help you shoot forward, as well as FF Blast Max and FF Turbo cushioning for a bouncy feel underfoot.<a class="view-deal button" href="https://www.amazon.com/Asics-SONICBLAST-Running-Winter-Stillwater/dp/B0DPLQ32YV" target="_blank" rel="nofollow" data-dimension112="c01c4950-c990-11f1-90e0-a54efa81122b" data-action="Deal Block" data-label="Sonicblast Road Running Shoes (Men's)" data-dimension48="Sonicblast Road Running Shoes (Men's)" data-dimension25="$94">View Deal</a></p></div><div class="product"><a data-dimension112="211001a8-cb9d-11f1-9160-758de2e1b850" data-action="Deal Block" data-label="Novablast 5 (Men's)" data-dimension48="Novablast 5 (Men's)" data-dimension25="$129" href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1166px;"><p class="vanilla-image-block" style="padding-top:48.80%;"><img id="4pk4xESon4iEcQDmd7TqZF" name="Novablast 5 (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/4pk4xESon4iEcQDmd7TqZF-1920-80.jpg" mos="" align="middle" fullscreen="" width="1166" height="569" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow" data-dimension112="211001a8-cb9d-11f1-9160-758de2e1b850" data-action="Deal Block" data-label="Novablast 5 (Men's)" data-dimension48="Novablast 5 (Men's)" data-dimension25="$129">Novablast 5 (Men's): was $160 now $129</a></strong><br />We voted the Asics Novablast 6 as the <a href="https://www.tomsguide.com/best-picks/best-running-shoes">best running shoes</a> you can buy right now, but before that, the <a href="https://www.tomsguide.com/wellness/running/asics-novablast-5-review">Asics Novablast 5</a> had the top spot. They quickly stood out for their balance of comfort, support and fun, making them a pair of shoes you will actually look forward to running in. They're lightweight, durable and have a soft, springy feel underfoot that helps absorb impact while keeping runs enjoyable.<a class="view-deal button" href="https://www.amazon.com/ASICS-NOVABLAST-Running-Shoes-Aurora/dp/B0FWYJD4VC" target="_blank" rel="nofollow" data-dimension112="211001a8-cb9d-11f1-9160-758de2e1b850" data-action="Deal Block" data-label="Novablast 5 (Men's)" data-dimension48="Novablast 5 (Men's)" data-dimension25="$129">View Deal</a></p></div><h3 class="article-body__section" id="section-best-brooks-deals"><span>Best Brooks Deals</span></h3><div class="product"><a data-dimension112="c01c4a40-c990-11f1-af5c-0dc2fe444d53" data-action="Deal Block" data-label="Caldera 8 Ultra Trail Running Shoe (Women's)" data-dimension48="Caldera 8 Ultra Trail Running Shoe (Women's)" data-dimension25="$89" href="https://www.amazon.com/Brooks-Womens-Caldera-Ultra-Running/dp/B0D3JB13WZ" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1097px;"><p class="vanilla-image-block" style="padding-top:63.35%;"><img id="2djj2QHTebGwfGjm4tKjFa" name="Brooks Caldera" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/2djj2QHTebGwfGjm4tKjFa-1920-80.jpg" mos="" align="middle" fullscreen="" width="1097" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Brooks-Womens-Caldera-Ultra-Running/dp/B0D3JB13WZ" target="_blank" rel="nofollow" data-dimension112="c01c4a40-c990-11f1-af5c-0dc2fe444d53" data-action="Deal Block" data-label="Caldera 8 Ultra Trail Running Shoe (Women's)" data-dimension48="Caldera 8 Ultra Trail Running Shoe (Women's)" data-dimension25="$89">Caldera 8 Ultra Trail Running Shoe (Women's): was $149 now $89</a></strong><br />The Brooks Caldera 8 Ultra Trail is built for going the distance on uneven terrain. It has plenty of cushioning alongside all that necessary traction for tackling the trails, and it has high sidewalls to keep your feet nice and stable.<a class="view-deal button" href="https://www.amazon.com/Brooks-Womens-Caldera-Ultra-Running/dp/B0D3JB13WZ" target="_blank" rel="nofollow" data-dimension112="c01c4a40-c990-11f1-af5c-0dc2fe444d53" data-action="Deal Block" data-label="Caldera 8 Ultra Trail Running Shoe (Women's)" data-dimension48="Caldera 8 Ultra Trail Running Shoe (Women's)" data-dimension25="$89">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4b1c-c990-11f1-b7c6-2b0013333224" data-action="Deal Block" data-label="Hyperion Max 3 (Men's)" data-dimension48="Hyperion Max 3 (Men's)" data-dimension25="$108" href="https://www.amazon.com/dp/B0DM3MTXGK?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:840px;"><p class="vanilla-image-block" style="padding-top:68.45%;"><img id="bf7gzstL3kTG3roVNuaN4L" name="Brooks Hyperion Max" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bf7gzstL3kTG3roVNuaN4L-1920-80.png" mos="" align="middle" fullscreen="" width="840" height="575" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0DM3MTXGK?" target="_blank" rel="nofollow" data-dimension112="c01c4b1c-c990-11f1-b7c6-2b0013333224" data-action="Deal Block" data-label="Hyperion Max 3 (Men's)" data-dimension48="Hyperion Max 3 (Men's)" data-dimension25="$108">Hyperion Max 3 (Men's): was $199 now $108</a></strong><br />The Brooks Hyperion Max 3 is a plated training shoe with a mega-stack of cushioning in its midsole, the top layer of which is made from a particularly springy PEBA material. It's a speedier option than shoes like the Glycerin and Ghost, and still comfortable for easy runs as well.<a class="view-deal button" href="https://www.amazon.com/dp/B0DM3MTXGK?" target="_blank" rel="nofollow" data-dimension112="c01c4b1c-c990-11f1-b7c6-2b0013333224" data-action="Deal Block" data-label="Hyperion Max 3 (Men's)" data-dimension48="Hyperion Max 3 (Men's)" data-dimension25="$108">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4b9e-c990-11f1-ae63-71c4afc87ea1" data-action="Deal Block" data-label="Ghost Max 3 (Men's)" data-dimension48="Ghost Max 3 (Men's)" data-dimension25="$109" href="https://www.amazon.com/dp/B0DM3R7VD1?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:890px;"><p class="vanilla-image-block" style="padding-top:64.61%;"><img id="mL6eZbPdx2NmSyzvQSMAcc" name="Brooks Ghost Max 3" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/mL6eZbPdx2NmSyzvQSMAcc-1920-80.png" mos="" align="middle" fullscreen="" width="890" height="575" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0DM3R7VD1?" target="_blank" rel="nofollow" data-dimension112="c01c4b9e-c990-11f1-ae63-71c4afc87ea1" data-action="Deal Block" data-label="Ghost Max 3 (Men's)" data-dimension48="Ghost Max 3 (Men's)" data-dimension25="$109">Ghost Max 3 (Men's): was $159 now $109</a></strong><br />The Ghost Max 3 is a more cushioned and rockered alternative to the Ghost 17, and I prefer the ride of the shoe myself to the classic Ghost. The Ghost Max 4 has just come out, meaning the Ghost Max 3 is reduced by $50, with almost all colors and sizes included in the sale.<a class="view-deal button" href="https://www.amazon.com/dp/B0DM3R7VD1?" target="_blank" rel="nofollow" data-dimension112="c01c4b9e-c990-11f1-ae63-71c4afc87ea1" data-action="Deal Block" data-label="Ghost Max 3 (Men's)" data-dimension48="Ghost Max 3 (Men's)" data-dimension25="$109">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4c16-c990-11f1-bc3b-e7f4af19bbfb" data-action="Deal Block" data-label="Glycerin Max (Women's)" data-dimension48="Glycerin Max (Women's)" data-dimension25="$149" href="https://www.amazon.com/Brooks-Womens-Glycerin-Peacoat-Ribbon/dp/B0D3B6HXJ7" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:926px;"><p class="vanilla-image-block" style="padding-top:62.10%;"><img id="Y98AvyBg8eBD4Re2iRNXC6" name="Brooks Gycerin Max" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Y98AvyBg8eBD4Re2iRNXC6-1920-80.png" mos="" align="middle" fullscreen="" width="926" height="575" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Brooks-Womens-Glycerin-Peacoat-Ribbon/dp/B0D3B6HXJ7" target="_blank" rel="nofollow" data-dimension112="c01c4c16-c990-11f1-bc3b-e7f4af19bbfb" data-action="Deal Block" data-label="Glycerin Max (Women's)" data-dimension48="Glycerin Max (Women's)" data-dimension25="$149">Glycerin Max (Women's): was $199 now $149</a></strong><br />The original Glycerin Max is not just $50 cheaper than the Glycerin Max 2 thanks to this deal, I also think it's better than the latest model because it's a bit lighter. This is the most cushioned model in the Brooks' line-up, and perfect for anyone who loves a comfortable running shoe.<a class="view-deal button" href="https://www.amazon.com/Brooks-Womens-Glycerin-Peacoat-Ribbon/dp/B0D3B6HXJ7" target="_blank" rel="nofollow" data-dimension112="c01c4c16-c990-11f1-bc3b-e7f4af19bbfb" data-action="Deal Block" data-label="Glycerin Max (Women's)" data-dimension48="Glycerin Max (Women's)" data-dimension25="$149">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4c8e-c990-11f1-9fdd-93c65e5a479e" data-action="Deal Block" data-label="Hyperion Elite 5" data-dimension48="Hyperion Elite 5" data-dimension25="$149" href="https://www.amazon.com/dp/B0F4NG15WR?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:980px;"><p class="vanilla-image-block" style="padding-top:58.67%;"><img id="ZsxwPp8UrjYaq3Tu7V3wud" name="Brooks Hyperion Elite 5" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/ZsxwPp8UrjYaq3Tu7V3wud-1920-80.png" mos="" align="middle" fullscreen="" width="980" height="575" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>When it comes to running fast, carbon plate racers are the shoe to go for, but they're normally prohibitively expensive. Thanks to this $75 saving the Brooks Hyperion Elite 5 is under $200 in the Amazon sale. It's still not exactly cheap, but if you have PRs in mind, it will help get you there with its lightweight, propulsive design.<a class="view-deal button" href="https://www.amazon.com/dp/B0F4NG15WR?" target="_blank" rel="nofollow" data-dimension112="c01c4c8e-c990-11f1-9fdd-93c65e5a479e" data-action="Deal Block" data-label="Hyperion Elite 5" data-dimension48="Hyperion Elite 5" data-dimension25="$149">View Deal</a></p></div><h3 class="article-body__section" id="section-best-hoka-deals"><span>Best Hoka Deals</span></h3><div class="product"><a data-dimension112="c01c4d88-c990-11f1-b97f-91ade45f2509" data-action="Deal Block" data-label="Arahi 8 (Women's)" data-dimension48="Arahi 8 (Women's)" data-dimension25="$120" href="https://www.hoka.com/en/us/womens-everyday-running-shoes/arahi-8/1168691.html?dwvar_1168691_color=FSTS" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1932px;"><p class="vanilla-image-block" style="padding-top:81.11%;"><img id="EUf3iisgBNqSoAfRcsnYMU" name="Arahi 8" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/EUf3iisgBNqSoAfRcsnYMU-1920-80.jpg" mos="" align="middle" fullscreen="" width="1932" height="1567" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/womens-everyday-running-shoes/arahi-8/1168691.html?dwvar_1168691_color=FSTS" target="_blank" rel="nofollow" data-dimension112="c01c4d88-c990-11f1-b97f-91ade45f2509" data-action="Deal Block" data-label="Arahi 8 (Women's)" data-dimension48="Arahi 8 (Women's)" data-dimension25="$120">Arahi 8 (Women's): was $150 now $120</a></strong><br />The Arahi 8 is the stable counterpart to the Clifton 10, offering extra support for runners who overpronate along with Hoka's familiar smooth, cushioned ride. It'd great for neutral runners, and the newer Arahi 9 is very similar in all respects, so the older model is definitely better value in the sale.<a class="view-deal button" href="https://www.hoka.com/en/us/womens-everyday-running-shoes/arahi-8/1168691.html?dwvar_1168691_color=FSTS" target="_blank" rel="nofollow" data-dimension112="c01c4d88-c990-11f1-b97f-91ade45f2509" data-action="Deal Block" data-label="Arahi 8 (Women's)" data-dimension48="Arahi 8 (Women's)" data-dimension25="$120">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4e00-c990-11f1-bb6f-9db9b30dcbde" data-action="Deal Block" data-label="Challenger 8 (Men's)" data-dimension48="Challenger 8 (Men's)" data-dimension25="$124" href="https://www.hoka.com/en/us/mens-trail/challenger-8/1168716.html?dwvar_1168716_color=WNH" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1932px;"><p class="vanilla-image-block" style="padding-top:81.11%;"><img id="3XcNm4G4Mycujx4hDGuqPU" name="Challenger" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3XcNm4G4Mycujx4hDGuqPU-1920-80.jpg" mos="" align="middle" fullscreen="" width="1932" height="1567" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/mens-trail/challenger-8/1168716.html?dwvar_1168716_color=WNH" target="_blank" rel="nofollow" data-dimension112="c01c4e00-c990-11f1-bb6f-9db9b30dcbde" data-action="Deal Block" data-label="Challenger 8 (Men's)" data-dimension48="Challenger 8 (Men's)" data-dimension25="$124">Challenger 8 (Men's): was $155 now $124</a></strong><br />The Hoka Challenger 8 is great for its versatility, because it grips well on both roads and light trails, and is comfortable for runs of any distance. It's also a great hiking shoe and can be worn before, during and after your runs. <a class="view-deal button" href="https://www.hoka.com/en/us/mens-trail/challenger-8/1168716.html?dwvar_1168716_color=WNH" target="_blank" rel="nofollow" data-dimension112="c01c4e00-c990-11f1-bb6f-9db9b30dcbde" data-action="Deal Block" data-label="Challenger 8 (Men's)" data-dimension48="Challenger 8 (Men's)" data-dimension25="$124">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4e78-c990-11f1-b993-d79635ad2a4a" data-action="Deal Block" data-label="Clifton 10 (Men's)" data-dimension48="Clifton 10 (Men's)" data-dimension25="$124" href="https://www.hoka.com/en/us/mens-everyday-running-gear/clifton-10/1162030.html?dwvar_1162030_color=WKY" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1932px;"><p class="vanilla-image-block" style="padding-top:81.11%;"><img id="pTkmatx4tcURfCFTcWdCu9" name="Clifton 10" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pTkmatx4tcURfCFTcWdCu9-1920-80.jpg" mos="" align="middle" fullscreen="" width="1932" height="1567" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/mens-everyday-running-gear/clifton-10/1162030.html?dwvar_1162030_color=WKY" target="_blank" rel="nofollow" data-dimension112="c01c4e78-c990-11f1-b993-d79635ad2a4a" data-action="Deal Block" data-label="Clifton 10 (Men's)" data-dimension48="Clifton 10 (Men's)" data-dimension25="$124">Clifton 10 (Men's): was $155 now $124</a></strong><br />The Clifton is the most popular Hoka running shoe for a reason. It’s the perfect place to start with the brand, offering a smooth, comfortable ride that will suit runners of all levels well. It also offers better value than Hoka's rivals, like the Bondi 9.<a class="view-deal button" href="https://www.hoka.com/en/us/mens-everyday-running-gear/clifton-10/1162030.html?dwvar_1162030_color=WKY" target="_blank" rel="nofollow" data-dimension112="c01c4e78-c990-11f1-b993-d79635ad2a4a" data-action="Deal Block" data-label="Clifton 10 (Men's)" data-dimension48="Clifton 10 (Men's)" data-dimension25="$124">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4efa-c990-11f1-a8a0-db7454b62b4b" data-action="Deal Block" data-label="Clifton 9 GTX (Women's)" data-dimension48="Clifton 9 GTX (Women's)" data-dimension25="$132" href="https://www.hoka.com/en/us/womens-everyday-running-shoes/clifton-9-gtx/1141490.html?dwvar_1141490_color=BNDR" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1932px;"><p class="vanilla-image-block" style="padding-top:81.11%;"><img id="RRxC8fKVUmNBdxEfjnVQFf" name="Clifton 9 GTX (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/RRxC8fKVUmNBdxEfjnVQFf-1920-80.webp" mos="" align="middle" fullscreen="" width="1932" height="1567" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/womens-everyday-running-shoes/clifton-9-gtx/1141490.html?dwvar_1141490_color=BNDR" target="_blank" rel="nofollow" data-dimension112="c01c4efa-c990-11f1-a8a0-db7454b62b4b" data-action="Deal Block" data-label="Clifton 9 GTX (Women's)" data-dimension48="Clifton 9 GTX (Women's)" data-dimension25="$132">Clifton 9 GTX (Women's): was $165 now $132</a></strong><br />The <a href="https://www.tomsguide.com/reviews/hoka-clifton-9">Hoka Clifton 9</a> is a cushioned, everyday running shoe that’ll work well for beginners and more experienced runners alike. It’s not the fanciest or the fastest shoe around, but it’s reliably comfortable, whether you’re training for a marathon or using this shoe for your walking workouts. The GTX version adds weatherproofing, so you'll get more out of your walks and runs, rain or shine.<a class="view-deal button" href="https://www.hoka.com/en/us/womens-everyday-running-shoes/clifton-9-gtx/1141490.html?dwvar_1141490_color=BNDR" target="_blank" rel="nofollow" data-dimension112="c01c4efa-c990-11f1-a8a0-db7454b62b4b" data-action="Deal Block" data-label="Clifton 9 GTX (Women's)" data-dimension48="Clifton 9 GTX (Women's)" data-dimension25="$132">View Deal</a></p></div><div class="product"><a data-dimension112="c01c4f72-c990-11f1-93d2-330f9e5c8d04" data-action="Deal Block" data-label="Mafate Speed 2 (Unisex)" data-dimension48="Mafate Speed 2 (Unisex)" data-dimension25="$136" href="https://www.hoka.com/en/us/all-gender-footwear/mafate-speed-2/1126851.html?dwvar_1126851_color=BWHT" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1932px;"><p class="vanilla-image-block" style="padding-top:81.11%;"><img id="9K5YzNyJZBd44NsmvkK3zX" name="Mafate Speed 2" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/9K5YzNyJZBd44NsmvkK3zX-1920-80.jpg" mos="" align="middle" fullscreen="" width="1932" height="1567" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.hoka.com/en/us/all-gender-footwear/mafate-speed-2/1126851.html?dwvar_1126851_color=BWHT" target="_blank" rel="nofollow" data-dimension112="c01c4f72-c990-11f1-93d2-330f9e5c8d04" data-action="Deal Block" data-label="Mafate Speed 2 (Unisex)" data-dimension48="Mafate Speed 2 (Unisex)" data-dimension25="$136">Mafate Speed 2 (Unisex): was $170 now $136</a></strong><br />Right now, the Hoka Mafate 2 is 20% off. It provides extra cushioning and protection for long, tough, technical trails—ideal for ultra-distance runs. It’s a bit heavier than the Speedgoat 6 but is designed for comfort mile after mile. <a class="view-deal button" href="https://www.hoka.com/en/us/all-gender-footwear/mafate-speed-2/1126851.html?dwvar_1126851_color=BWHT" target="_blank" rel="nofollow" data-dimension112="c01c4f72-c990-11f1-93d2-330f9e5c8d04" data-action="Deal Block" data-label="Mafate Speed 2 (Unisex)" data-dimension48="Mafate Speed 2 (Unisex)" data-dimension25="$136">View Deal</a></p></div><h3 class="article-body__section" id="section-best-nike-deals"><span>Best Nike Deals</span></h3><div class="product"><a data-dimension112="c01c5062-c990-11f1-b512-b716997cca4f" data-action="Deal Block" data-label="Air Max Alpha Trainer 6 Workout Shoes (Men's)" data-dimension48="Air Max Alpha Trainer 6 Workout Shoes (Men's)" data-dimension25="$79" href="https://www.amazon.com/dp/B0FQN1FHK9?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1618px;"><p class="vanilla-image-block" style="padding-top:45.67%;"><img id="pk5XnTCWLaWiYRnXrqNnt5" name="Air Max Alpha Trainer 6 Workout Shoes (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pk5XnTCWLaWiYRnXrqNnt5-1920-80.jpg" mos="" align="middle" fullscreen="" width="1618" height="739" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0FQN1FHK9?" target="_blank" rel="nofollow" data-dimension112="c01c5062-c990-11f1-b512-b716997cca4f" data-action="Deal Block" data-label="Air Max Alpha Trainer 6 Workout Shoes (Men's)" data-dimension48="Air Max Alpha Trainer 6 Workout Shoes (Men's)" data-dimension25="$79">Air Max Alpha Trainer 6 Workout Shoes (Men's): was $100 now $79</a></strong><br />Super cushioned and perfect for all kinds of workouts, these Nike shoes have dropped in price. They're designed to be stable and flexible and have a rubber wrap to keep your feet in place. Their simple style means they go with any kind of workout gear, too.<a class="view-deal button" href="https://www.amazon.com/dp/B0FQN1FHK9?" target="_blank" rel="nofollow" data-dimension112="c01c5062-c990-11f1-b512-b716997cca4f" data-action="Deal Block" data-label="Air Max Alpha Trainer 6 Workout Shoes (Men's)" data-dimension48="Air Max Alpha Trainer 6 Workout Shoes (Men's)" data-dimension25="$79">View Deal</a></p></div><div class="product"><a data-dimension112="c01c50da-c990-11f1-a981-71bebbd4a682" data-action="Deal Block" data-label="Pegasus 41 Running Shoes (Women's)" data-dimension48="Pegasus 41 Running Shoes (Women's)" data-dimension25="$99" href="https://www.amazon.com/dp/B0F2G75S6N?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:44.60%;"><img id="8rtJszfW7dGEJYJc4He9CN" name="81O2j-efNTL._AC_SX695_" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/8rtJszfW7dGEJYJc4He9CN-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="310" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0F2G75S6N?" target="_blank" rel="nofollow" data-dimension112="c01c50da-c990-11f1-a981-71bebbd4a682" data-action="Deal Block" data-label="Pegasus 41 Running Shoes (Women's)" data-dimension48="Pegasus 41 Running Shoes (Women's)" data-dimension25="$99">Pegasus 41 Running Shoes (Women's): was $140 now $99</a></strong><br />The Pegasus 41 is Nike's popular daily trainer, and the 41st version of the shoe is our favorite yet. The new ReactX midsole and higher stack on the Pegasus 41 give it a softer ride than its predecessors, but it’s not so squishy underfoot as to be unstable in any way. It’s a balanced midsole that is comfortable for easy and long runs, but has a little bounce to it when you want to up the pace. Read our full <a href="https://www.tomsguide.com/wellness/running/i-ran-35-miles-in-the-nike-pegasus-41-and-its-my-favorite-pegasus-in-years">Nike Pegasus 41 review</a> here to find out more.<a class="view-deal button" href="https://www.amazon.com/dp/B0F2G75S6N?" target="_blank" rel="nofollow" data-dimension112="c01c50da-c990-11f1-a981-71bebbd4a682" data-action="Deal Block" data-label="Pegasus 41 Running Shoes (Women's)" data-dimension48="Pegasus 41 Running Shoes (Women's)" data-dimension25="$99">View Deal</a></p></div><div class="product"><a data-dimension112="c01c515c-c990-11f1-98a6-33fcfc026737" data-action="Deal Block" data-label="Vomero 18 Running Shoes (Women's)" data-dimension48="Vomero 18 Running Shoes (Women's)" data-dimension25="$121" href="https://www.amazon.com/dp/B0F2G9VV4R?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:44.46%;"><img id="on8DUvsokY6RbJszwfXseQ" name="Vomero" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/on8DUvsokY6RbJszwfXseQ-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="309" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0F2G9VV4R?" target="_blank" rel="nofollow" data-dimension112="c01c515c-c990-11f1-98a6-33fcfc026737" data-action="Deal Block" data-label="Vomero 18 Running Shoes (Women's)" data-dimension48="Vomero 18 Running Shoes (Women's)" data-dimension25="$121">Vomero 18 Running Shoes (Women's): was $150 now $121</a></strong><br />The <a href="https://www.tomsguide.com/wellness/running/nike-vomero-18-review">Nike Vomero 18</a> is a max-cushioned cruiser that's ideal for protecting the body on long and easy runs. It's plush, comfortable and stable. The shoe is pretty heavy, but if you're looking for plush, sink-in comfort, this one ticks that box. <a class="view-deal button" href="https://www.amazon.com/dp/B0F2G9VV4R?" target="_blank" rel="nofollow" data-dimension112="c01c515c-c990-11f1-98a6-33fcfc026737" data-action="Deal Block" data-label="Vomero 18 Running Shoes (Women's)" data-dimension48="Vomero 18 Running Shoes (Women's)" data-dimension25="$121">View Deal</a></p></div><h3 class="article-body__section" id="section-best-saucony-deals"><span>Best Saucony Deals</span></h3><div class="product"><a data-dimension112="c01c524c-c990-11f1-8ae8-7f763e5ec426" data-action="Deal Block" data-label="Cohesion 14 Shoes (Women's)" data-dimension48="Cohesion 14 Shoes (Women's)" data-dimension25="$49" href="https://www.amazon.com/dp/B08CGR4YKG?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:695px;"><p class="vanilla-image-block" style="padding-top:58.99%;"><img id="pdjLV6pX6UWTGkcfsqaSE3" name="Cohesion 14 Shoes (Women's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/pdjLV6pX6UWTGkcfsqaSE3-1920-80.jpg" mos="" align="middle" fullscreen="" width="695" height="410" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B08CGR4YKG?" target="_blank" rel="nofollow" data-dimension112="c01c524c-c990-11f1-8ae8-7f763e5ec426" data-action="Deal Block" data-label="Cohesion 14 Shoes (Women's)" data-dimension48="Cohesion 14 Shoes (Women's)" data-dimension25="$49">Cohesion 14 Shoes (Women's): was $75 now $49</a></strong><br />The Saucony Cohesion 14 were already budget-friendly at $75, but now you can get a pair for even less. Shoppers on Amazon love these shoes for their comfortable and supportive design, earning these a 4.1-star rating.<a class="view-deal button" href="https://www.amazon.com/dp/B08CGR4YKG?" target="_blank" rel="nofollow" data-dimension112="c01c524c-c990-11f1-8ae8-7f763e5ec426" data-action="Deal Block" data-label="Cohesion 14 Shoes (Women's)" data-dimension48="Cohesion 14 Shoes (Women's)" data-dimension25="$49">View Deal</a></p></div><div class="product"><a data-dimension112="c01c52ce-c990-11f1-8d27-a3101f90107b" data-action="Deal Block" data-label="Tide 2 Trainer (Men's)" data-dimension48="Tide 2 Trainer (Men's)" data-dimension25="$65" href="https://www.amazon.com/dp/B0D31XXWHZ?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1200px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="gPCzUDufYEii6Von4ywQm" name="image" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gPCzUDufYEii6Von4ywQm-1920-80.png" mos="" align="middle" fullscreen="" width="1200" height="1200" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/dp/B0D31XXWHZ?" target="_blank" rel="nofollow" data-dimension112="c01c52ce-c990-11f1-8d27-a3101f90107b" data-action="Deal Block" data-label="Tide 2 Trainer (Men's)" data-dimension48="Tide 2 Trainer (Men's)" data-dimension25="$65">Tide 2 Trainer (Men's): was $100 now $65</a></strong><br />The Tide 2 is all about comfort for your everyday. It has soft, springy foam to make every step feel cushioned, a flexible plate to give you a little bounce and move with ease, <em>and</em> a breathable mesh upper to keep your feet cool. Basically, it’s perfect for walking, running errands, or just being on your feet all day without feeling sore.<a class="view-deal button" href="https://www.amazon.com/dp/B0D31XXWHZ?" target="_blank" rel="nofollow" data-dimension112="c01c52ce-c990-11f1-8d27-a3101f90107b" data-action="Deal Block" data-label="Tide 2 Trainer (Men's)" data-dimension48="Tide 2 Trainer (Men's)" data-dimension25="$65">View Deal</a></p></div><div class="product star-deal"><a data-dimension112="440e3b84-c99a-11f1-a464-f3c4efe14e10" data-action="Star Deal Block" data-label="Hurricane 24 (Men's)" data-dimension48="Hurricane 24 (Men's)" data-dimension25="$73" href="https://www.amazon.com/Saucony-Hurricane-Sneaker-Black-Shadow/dp/B0D31XQL4H" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1498px;"><p class="vanilla-image-block" style="padding-top:46.40%;"><img id="vxf7UD5T2Am7guVzFoFcZ4" name="Saucony Hurricane 24 deal block" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4-1920-80.jpg" mos="" align="middle" fullscreen="" width="1498" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Saucony-Hurricane-Sneaker-Black-Shadow/dp/B0D31XQL4H" target="_blank" rel="nofollow" data-dimension112="440e3b84-c99a-11f1-a464-f3c4efe14e10" data-action="Star Deal Block" data-label="Hurricane 24 (Men's)" data-dimension48="Hurricane 24 (Men's)" data-dimension25="$73">Hurricane 24 (Men's): was $82 now $73</a></strong><br />Running with the <a href="https://www.tomsguide.com/wellness/running/saucony-hurricane-24-review">Saucony Hurricane 24 </a>is like running on clouds. They use PWRRUN+ foam, which cushions your feet while still feeling springy. With a wide base and rocker design, it offers a stable and comfortable ride for longer or easy runs. The breathable mesh upper fits securely without being tight. The Hurricane 25 have replaced these shoes and they're currently <a href="https://www.amazon.com/Saucony-Mens-Hurricane-Sneaker-Iceberg/dp/B0DJWP4QHZ" target="_blank" rel="nofollow">on sale for $87</a>, but the 24 are the real bargain. <a class="view-deal button" href="https://www.amazon.com/Saucony-Hurricane-Sneaker-Black-Shadow/dp/B0D31XQL4H" target="_blank" rel="nofollow" data-dimension112="440e3b84-c99a-11f1-a464-f3c4efe14e10" data-action="Star Deal Block" data-label="Hurricane 24 (Men's)" data-dimension48="Hurricane 24 (Men's)" data-dimension25="$73">View Deal</a></p></div><div class="product"><a data-dimension112="c01c5346-c990-11f1-acc4-19b0a9479b2b" data-action="Deal Block" data-label="Ride 18 (Men's)" data-dimension48="Ride 18 (Men's)" data-dimension25="$81" href="https://www.amazon.com/Saucony-Mens-Sneaker-BLACK-WHITE/dp/B0D31WZWT8" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1542px;"><p class="vanilla-image-block" style="padding-top:45.07%;"><img id="NmXRUrbSqDWhK8xTzQF7bf" name="Ride 18 (Men's)" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/NmXRUrbSqDWhK8xTzQF7bf-1920-80.jpg" mos="" align="middle" fullscreen="" width="1542" height="695" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.amazon.com/Saucony-Mens-Sneaker-BLACK-WHITE/dp/B0D31WZWT8" target="_blank" rel="nofollow" data-dimension112="c01c5346-c990-11f1-acc4-19b0a9479b2b" data-action="Deal Block" data-label="Ride 18 (Men's)" data-dimension48="Ride 18 (Men's)" data-dimension25="$81">Ride 18 (Men's): was $145 now $81</a></strong><br />Comfort and support matter, and the <a href="https://www.tomsguide.com/wellness/fitness/i-ran-45-miles-in-the-saucony-ride-18-heres-my-verdict">Saucony Ride 18</a> delivers both. The soft, bouncy PWRRUN Plus foam feels light underfoot, helping to take the pressure off your joints as you build confidence. The stretchy mesh upper moves with your foot while the padded heel reduces rubbing that can cut runs short. Whether you’re lacing up for your first 5K or logging serious mileage, this shoe is a reliable all-rounder.<a class="view-deal button" href="https://www.amazon.com/Saucony-Mens-Sneaker-BLACK-WHITE/dp/B0D31WZWT8" target="_blank" rel="nofollow" data-dimension112="c01c5346-c990-11f1-acc4-19b0a9479b2b" data-action="Deal Block" data-label="Ride 18 (Men's)" data-dimension48="Ride 18 (Men's)" data-dimension25="$81">View Deal</a></p></div><h3 class="article-body__section" id="section-shop-more-deals"><span>Shop More Deals</span></h3><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Sneakers%2C+running+shoes%2C+sandals&amp;brands=Hoka%2CSkechers%2CAsics&amp;view_mode=carousel&amp;widget_title=Top+Deals+Handpicked+by+Our+Editors&amp;widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&amp;bg_color=light_blue" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters {      display: flex;      gap: 12px;      justify-content: center;      flex-wrap: wrap;    }    .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);      display: -webkit-box;      -webkit-line-clamp: 2;      -webkit-box-orient: vertical;      overflow: hidden;    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    .tg-df-container .tg-df-card-cta.tg-df-cta-savings-squad {      background-color: #3c8d0d;    }    .tg-df-card:hover .tg-df-card-cta.tg-df-cta-savings-squad,    .tg-df-card-cta.tg-df-cta-savings-squad:hover {      background-color: #2b6509;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 0;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 0 16px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }            .tg-df-filters {        width: calc(100% + 32px);        margin: 0 -16px;        padding: 0 16px 4px 16px;        display: flex;        justify-content: flex-start;        gap: 8px;        flex-wrap: nowrap;        overflow-x: auto;        -webkit-overflow-scrolling: touch;        scrollbar-width: none;      }      .tg-df-filters::after {        content: "";        display: block;        flex: 0 0 8px;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }            .tg-df-sort-wrapper {        flex: 0 0 max(42%, 130px);        min-width: 0;      }      .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;        -webkit-line-clamp: 3;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        -webkit-line-clamp: 3;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 16px;      text-align: center;      width: 100%;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: #f8fafc;      border-color: #cbd5e1;    }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right {      background-color: rgba(255, 255, 255, 0.4);      border: none;      box-shadow: none;      backdrop-filter: blur(4px);      -webkit-backdrop-filter: blur(4px);    }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right { right: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-right { right: 0; }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left:hover,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);      border: none;    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-carousel-roundels::after {      content: "";      flex: 0 0 32px;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;      transition: font-weight 0.2s;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-label {      font-weight: 700;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;      display: inline-flex;      align-items: center;      justify-content: center;      min-height: 36px;      box-sizing: border-box;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::after {      content: "";      flex: 0 0 32px;    }    .tg-df-grid-wrapper {      position: relative;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card {      flex: 0 0 auto;      width: 100px;      border-radius: 15px;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      border: 2px solid #1e293b;      background: white;      color: #1e293b;      display: flex;      flex-direction: column;      justify-content: center;      align-items: center;      font-weight: 600;      font-size: 14px;      cursor: pointer;      padding: 16px;      text-align: center;      transition: all 0.2s;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card:hover {      background: #1e293b;      color: white;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      -webkit-line-clamp: 2;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {      -webkit-line-clamp: 3;    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.45);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #5aaf0b; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #4a9109; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>          \x3C/div>          \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">      \x3Cdiv class="tg-df-top-bar">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>                \x3Cdiv class="tg-df-settings-wrapper">          \x3Cbutton type="button" class="tg-df-settings-btn" aria-label="Settings" id="tg-df-settings-toggle">            \x3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20">                \x3Cpath d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.73 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .43-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.49-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/>            \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-settings-dropdown-backdrop" id="tg-df-settings-backdrop">\x3C/div>          \x3Cdiv class="tg-df-settings-dropdown" id="tg-df-settings-panel">            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Search Region\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-region-select">                \x3Coption value="auto">🌍 Auto-detect\x3C/option>                \x3Coption value="US">🇺🇸 United States (US)\x3C/option>                \x3Coption value="GB">🇬🇧 United Kingdom (UK)\x3C/option>                \x3Coption value="CA">🇨🇦 Canada (CA)\x3C/option>                \x3Coption value="AU">🇦🇺 Australia (AU)\x3C/option>                \x3Coption value="DE">🇩🇪 Germany (DE)\x3C/option>                \x3Coption value="FR">🇫🇷 France (FR)\x3C/option>                \x3Coption value="IT">🇮🇹 Italy (IT)\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Retailer\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-retailer-select">                \x3Coption value="">All Retailers\x3C/option>                \x3Coption value="Amazon">Amazon\x3C/option>                \x3Coption value="Walmart">Walmart\x3C/option>                \x3Coption value="Best Buy">Best Buy\x3C/option>                \x3Coption value="Target">Target\x3C/option>                \x3Coption value="John Lewis">John Lewis\x3C/option>                \x3Coption value="Currys">Currys\x3C/option>                \x3Coption value="Argos">Argos\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Offer Type\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-offer-type-select">                \x3Coption value="">All Offers\x3C/option>                \x3Coption value="amazon_prime">Amazon Prime\x3C/option>                \x3Coption value="recommended_promo">Recommended Promo\x3C/option>                \x3Coption value="amazon_lightning">Amazon Lightning Deal\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Result Count\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-rows-select">                \x3Coption value="3">3 Items\x3C/option>                \x3Coption value="4">4 Items\x3C/option>                \x3Coption value="6">6 Items\x3C/option>                \x3Coption value="12" selected>12 Items\x3C/option>                \x3Coption value="24">24 Items\x3C/option>                \x3Coption value="48">48 Items\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Deal Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Only show products with active offers or previous prices (was_price)\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-deal-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Editor Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Enable multi-select to copy deals to CMS\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-editor-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">View Mode\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-view-mode-select">                \x3Coption value="auto">Auto Collection\x3C/option>                \x3Coption value="carousel">Carousel\x3C/option>                \x3Coption value="savings_squad">Savings Squad\x3C/option>                \x3Coption value="grid">Grid (Columns)\x3C/option>                \x3Coption value="row">Row (List)\x3C/option>              \x3C/select>            \x3C/div>          \x3C/div>        \x3C/div>      \x3C/div>      \x3Cdiv class="tg-df-filters">        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M9 3L5 6.99h3V14h2V6.99h3L9 3zm7 14.01V10h-2v7.01h-3L15 21l4-3.99h-3z"/>          \x3C/svg>          \x3Cselect class="tg-df-sort-select" aria-label="Sort Deals">            \x3Coption value="date_desc">Newest First\x3C/option>            \x3Coption value="best_match">Sort by: Match\x3C/option>            \x3Coption value="price_asc">Price Low to High\x3C/option>            \x3Coption value="price_desc">Price High to Low\x3C/option>            \x3Coption value="discount_desc">Biggest Discount\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>        \x3C/div>      \x3C/div>    \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();            if (['carousel', 'carousel-compact', 'auto', 'grid', 'row'].includes(this.getViewMode())) { this.loadCarouselSpreadsheet(); }        }        getViewMode() {          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          if (mode === 'carousel' || mode === 'auto' || mode === 'grid' || mode === 'row') {             if (mode === 'carousel') this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container') && mode === 'carousel') {               this.root.classList.add('is-carousel');             } else if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Everything';             if (this.discountFilter && !params.has('min_discount_ratio')) {               this.discountFilter.value = '5';             }          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (params.has('bg_color')) {            const bg = params.get('bg_color');            if (bg === 'white') {              this.root.style.setProperty('background-color', '#ffffff', 'important');            } else if (bg === 'transparent') {              this.root.style.setProperty('background-color', 'transparent', 'important');            } else if (bg === 'light_blue') {              this.root.style.setProperty('background-color', '#E7F0FF', 'important');            }          } else {             this.root.style.removeProperty('background-color');          }                    if (params.has('view_mode')) {            if (this.viewModeSelect) {              this.viewModeSelect.value = params.get('view_mode');            } else {              this.viewModeOverride = params.get('view_mode');            }          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'discount_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            this.searchInput.value = this.currentQuery;          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'discount_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const roundels = this.root.querySelectorAll('.tg-df-carousel-cat.original-hardcoded');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              if (this.getViewMode() === 'savings_squad' && this.autocompleteDropdown && this.airedaleTags && query.length > 0) {                 const matches = this.airedaleTags.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase()).slice(0, 5);                 if (matches.length > 0) {                    this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                    this.autocompleteDropdown.classList.add('active');                 } else {                    this.autocompleteDropdown.classList.remove('active');                 }              } else if (this.autocompleteDropdown) {                 this.autocompleteDropdown.classList.remove('active');              }              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  this.deals = [];                  this.render();                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                this.activeDealTag = null;                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });              this.activeDealTag = null;              this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.fetchDeals(query);              }            });          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = this.viewModeSelect.value === 'savings_squad' ? 'date_desc' : 'discount_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }                async loadCarouselSpreadsheet() {          try {              const parseCSVRow = (str) => {                  let result = [], cur = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (inQuotes) {                          if (char === '"') {                              if (str[i + 1] === '"') { cur += '"'; i++; }                              else { inQuotes = false; }                          } else { cur += char; }                      } else {                          if (char === '"') { inQuotes = true; }                          else if (char === ',') { result.push(cur); cur = ''; }                          else { cur += char; }                      }                  }                  result.push(cur); return result;              };              const parseCSV = (str) => {                  const rows = []; let curRow = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (char === '"') inQuotes = !inQuotes;                      if ((char === '\n' || char === '\r') && !inQuotes) {                          if (char === '\r' && str[i+1] === '\n') i++;                          if (curRow) rows.push(parseCSVRow(curRow));                          curRow = '';                      } else { curRow += char; }                  }                  if (curRow) rows.push(parseCSVRow(curRow));                  return rows;              };              const preloadedCSV = decodeURIComponent(escape(atob("LCwxLDIsMyw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNQ0KUm91bmRlbCB0ZXh0LEFsbCxUVnMsRm9vdHdlYXIsQXBwYXJlbCxNYXR0cmVzZXMsQXBwbGlhbmNlcyxXZWFyYWJsZSB0ZWNoLEhlYWRwaG9uZXMsU21hcnQgSG9tZSxTcGVha2VycyxMYXB0b3BzLFRhYmxldHMsQ29tcHV0aW5nLFBob25lcyxHYW1pbmcsTGVnbw0KUm91bmRlbCBpbWFnZSxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL2FpLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3R2cy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvN2IzYTIyNGIwNzk2M2M2MjdiNmI5MDliZDc4MzM4MzZlMDJmZjgxOS5qcGcud2VicCxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy84NGRhYzVkNDhlZDJkNDQ4NTU5ZWJhNjdhY2U4MzE0Y2M2N2NjZDk0LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vcHJvZHVjdHMvY2Fyb3VzZWwvbWF0dHJlc3Nlcy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvNzY4ZTk3Y2ViMDcxODAxZmFlMjA5MTBkMDgyMGIxNmY3NDdhZjkzOS5qcGcud2VicCxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3dlbGxuZXNzLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL2hlYWRwaG9uZXMuanBnLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzg5NTM1YmVlYmUyMGRiYmQ0YTM0NmQ2ZDZiZGZlOTFkOGE4ODRhMjEuanBnLndlYnAsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9hdWRpby5qcGcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9sYXB0b3BzLmpwZyxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy8yMzk3NTY0ZWQ3YTVmZjk0N2U5YjZiMzBlNTRmNDc0OTRiODQxZjg5LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vcHJvZHVjdHMvY2Fyb3VzZWwvY29tcHV0aW5nLmpwZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Byb2R1Y3RzL2Nhcm91c2VsL3Bob25lcy5wbmcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9wcm9kdWN0cy9jYXJvdXNlbC9nYW1pbmcucG5nLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzRmNmM2MjFjYWMwYmMxYTg1ZDU5M2UzNTk0YmE1YjM0OWVmZmQyOTIuanBnLndlYnANClNlYXJjaCBRdWVyeSxFdmVyeXRoaW5nLFRlbGV2aXNpb25zLCJTbmVha2VycywgcnVubmluZyBzaG9lcywgc2FuZGFscyIsQ2xvdGhpbmcsTWF0dHJlc3NlcyxIb21lIEFwcGxpYW5jZXMsV2VhcmFibGVzICYgRml0bmVzcyBUZWNoLEhlYWRwaG9uZXMsSG9tZSBUZWNoLFNwZWFrZXJzLExhcHRvcHMsVGFibGV0cyxDb21wdXRpbmcsUGhvbmVzLEdhbWluZyxDb25zdHJ1Y3Rpb24gVG95cw0KRGlzY291bnQgQW1vdW50LG1pbiA1JSxtaW4gMTAlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUNClByaWNlIFJhbmdlLCwsLCxtaW4gJDQwMCwsLCxtaW4gJDI1LCxtaW4gJDMwMCwsLG1pbiAkMTAwLCwNCkJyYW5kIFNlbGVjdGlvbiwsLCwsLCwsLCwsLCwsLCwNCkZpbHRlciBidXR0b25zLCwsLCwsLCwsLCwsLCwsLA0KMSxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMNCjIsQW1hem9uIGRlYWxzLFVuZGVyICQxMDAwLDUwJSBvZmYsQWRpZGFzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsNTAlIG9mZixBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscw0KMyxPdmVyICQ0MDAsVW5kZXIgJDUwMCxIb2thLE5pa2UsU2FhdHZhLE5pbmphLDQwJSBvZmYsSkxhYiwsSkJMLERlbGwsLEFzdXMsQXBwbGUsQ29uc29sZXMsU3RhciBXYXJzDQo0LFVuZGVyICQxMDAwLDUwJSBvZmYsU2tlY2hlcnMsVW5kZXIgQXJtb3VyLEhlbGl4LFNoYXJrLEdhcm1pbixBbmtlciBTb3VuZGNvcmUsUmluZyxTb25vcyxBcHBsZSxBcHBsZSxUUC1saW5rLFNhbXN1bmcsQWNjZXNzb3JpZXMsVW5kZXIgJDI1DQo1LFVuZGVyICQ1MDAsTEcsQXNpY3MsQ29sdW1iaWEsRHJlYW1DbG91ZCxLZXVyaWcsQXBwbGUsU29ueSxHb3ZlZSxUcmliaXQsTGVub3ZvLFNhbXN1bmcsRWVybyxHb29nbGUsR2FtZXMsVW5kZXIgJDUwDQo2LDUwJSBvZmYsU2Ftc3VuZyxOaWtlLFBhdGFnb25pYSxOZWN0YXIsRGUnTG9uZ2hpLEFtYXpmaXQsQXBwbGUsS2FzYSBzbWFydCxTb255LEFsaWVud2FyZSxUQ0wsTmV0Z2VhcixNb3Rvcm9sYSxOaW50ZW5kbyxCb3RhbmljYWxzDQo3LEFtYXpvbixIaXNlbnNlLE5ldyBCYWxhbmNlLEFyYyd0ZXJ5eCxUZW1wdXItcGVkaWMsRHlzb24sRml0Yml0LEJlYXRzLFBoaWxpcHMgSHVlLEFua2VyLEFjZXIsT25lUGx1cyxEZWxsLE9uZVBsdXMsU29ueSxEaXNuZXkNCjgsQXBwbGUsVENMLEFkaWRhcyxDYXJoYXJ0dCxCZWFyLEJpc3NlbGwsU2Ftc3VuZyxFYXJmdW4sQmxpbmssQmVhdHMsTVNJLE1pY3Jvc29mdCxBY2VyLE5vdGhpbmcsWGJveCxNYXJ2ZWwNCjksLFNvbnksU2F1Y29ueSxUaGUgTm9ydGggRmFjZSxTaWVuYSxOdXRyaWJ1bGxldCxPdXJhLFNhbXN1bmcsR29vZ2xlIE5lc3QgLE1hcnNoYWxsLFNhbXN1bmcsTGVub3ZvLExlbm92bywsLFBva2Vtb24NCjEwLCxSb2t1LEJpcmtlbnN0b2NrLENSWiBZb2dhLFdpbmtCZWRzLEJsYWNrIGFuZCBEZWNrZXIsUmluZ2Nvbm4sQ01GLEV1ZnksU2Ftc3VuZyxNaWNyb3NvZnQsUmVNYXJrYWJsZSxBbGllbndhcmUsLCwNCjExLCwsQnJvb2tzLFRoZSBHeW0gUGVvcGxlLEJyb29rbHluIGJlZGRpbmcsTmVzcHJlc3NvLCwxTW9yZSxBcmxvLCxSYXplciwsQ29yc2FpciwsLA0KMTIsLCxDcm9jcywsRWlnaHQgU2xlZXAsQ3Vpc2luYXJ0LCxKQkwsLCwsLEhQLCwsDQpOb3RlcywsLCwsLCwsLCwsLCwsLCwNCiwsIlByaW9yaXRpc2UgYmlnZ2VzdCAlLyQgZGlzY291bnQsIFR2cyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiB0aGUgbW9zdCBwb3B1bGFyIGV2ZW4gaWYgdGhleSBhcmUgc3RpbGwgZXhwZW5zaXZlIiwiTm8gcGF0dGVybiB0byBwcmljaW5nL2Rpc2NvdW50LCByZWFkZXJzIG1haW5seSBzaG9wIGJ5IGJyYW5kL3JlY29nbmlzYWJsZSBzaG9lcyIsIk5vIHBhdHRlcm4gdG8gcHJpY2luZy9kaXNjb3VudCwgcmVhZGVycyBtYWlubHkgc2hvcCBieSBicmFuZCIsIkEgbGFiZWwgd2lsbCBkZWZpbml0ZWx5IGhlbHAgaGVyZSBlLmcuIGJlc3QgZm9yIHNpZGUgc2xlZXBlciwgYmVzdCBtZW1vcnkgZm9hbSIsIkFwcGxpYW5jZXMgaXMgYSBiaWcgY2F0ZWdvcnksIGlzIGl0IHBvc3NpYmxlIHRvIHNwbGl0IGludG8ga2l0Y2hlbiBhcHBsaWFuY2VzLCBmbG9vcmNhcmUsIGFpciBoZWFsdGgvY29vbGluZz8gT3Igc2ltaWxhciIsIkZvY3VzIG9uIHZhbHVlIGZvciBtb25leSwgR2FybWlucyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiBwb3B1bGFyIGV2ZW4gdGhvdWdoIHRoZXkgYXJlIHN0aWxsICQ1MDAiLCwsLCxJbmNsdWRlIEtpbmRsZXMsSSB3b3VsZCBpbmNsdWRlIHdpZmkgcm91dGVycyBoZXJlIGluc3RlYWQgb2Ygc21hcnQgaG9tZSxDYW4gd2Ugc3VyZmFjZSBwaG9uZSBwcm92aWRlciBkZWFscz8gVC1tb2JpbGUgYW5kIHZlcml6b24gd291bGQgbWFrZSBhIGxvdCBtb3JlIG1vbmV5IHRoYW4gQW1hem9uLCwNCiwsaGF2aW5nIGEgJ2Jlc3QgZm9yJyBsYWJlbCB3b3VsZCBiZSBoZWxwZnVsIGUuZy4gYmVzdCBmb3IgYnJpZ2h0IHJvb20sQ2FuIHdlIHN0b3Aga2lkcyBzaG9lcyBmcm9tIHB1bGxpbmcgdGhyb3VnaD8sIldpbGwgdGhpcyBpbmNsdWRlIGFjY2Vzc29yaWVzIGUuZy4gY2FwcywgYmFncywgaWYgc28gbWFrZSBzdXJlIHRoZXNlIGFyZSBtaXhlZCB0aHJvdWdob3V0IGNsb3RoaW5nIGRlYWxzIixXaWxsIHRoaXMgaW5jbHVkZSB0b3BwZXJzIGFuZCBwaWxsb3dzPyBTZWVpbmcgbW9yZSBtb21lbnR1bSB3aXRoIHRoaXMgY2F0ZWdvcnkgcmVjZW50bHkgc28gYSBiZWRkaW5nIHRhYiBtaWdodCB3b3JrLCwiTmVlZCB0byBtYWtlIHN1cmUgYmFuZHMsIHNjcmVlbiBwcm90ZWN0b3JzIGV0Yy4gZG9uJ3QgcHVsbCBpbnRvIGhlcmUiLCwsLCwsLCwsDQosLCJQcmlvcml0aXNlIDY1JycgYW5kIDU1JyBpbmNoIFRWcywgdGhlbiBiaWdnZXIgc2NyZWVucyBiZWZvcmUgdGhlIHNtYWxsZXIgc2l6ZXMiLCwsUXVlZW4gaXMgdGhlIG1vc3QgcG9wdWxhciBzaXplIGluIHRoZSBVUyAtIHByaW9yaXRpc2UgZGVhbHMgZm9yIHRoaXMgc2l6ZSwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpDYXRlZ29yaWVzIHRvIGNvbnNpZGVyLCxQcm9kdWN0cyBpbmNsdWRlZCwsLCwsLCwsLCwsLCwsDQpVbmRlciAkNTA/LCxBaXIgdGFncywsLCwsLCwsLCwsLCwsDQosLFBvcnRhYmxlIGNoYXJnZXJzL3dpcmVsZXNzIGNoYXJnZXJzLCwsLCwsLCwsLCwsLCwNCiwsIldhdGVyIGJvdHRsZXMgKHN0YW5sZXlzLCBPd2FsYSwgSHlkcm8gZmxhc2ssIFlldGkpIiwsLCwsLCwsLCwsLCwsDQosLEhhbmQgaGVsZCBmYW5zLCwsLCwsLCwsLCwsLCwNCiwsLCwsLCwsLCwsLCwsLCwNCmhvbWUgb2ZmaWNlLCxvZmZpY2UgY2hhaXJzLCwsLCwsLCwsLCwsLCwNCiwsc3RhbmRpbmcgZGVza3MsLCwsLCwsLCwsLCwsLA0KLCxtb25pdG9ycywsLCwsLCwsLCwsLCwsDQosLEtleWJvYXJkcywsLCwsLCwsLCwsLCwsDQosLGRvY2tpbmcgc3RhdGlvbiwsLCwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpHYW1pbmcsLENvbnNvbGVzLCwsLCwsLCwsLCwsLCwNCiwsQWNjZXNzb3JpZXMsLCwsLCwsLCwsLCwsLA0KLCxHYW1lcywsLCwsLCwsLCwsLCwsDQosLENvdWxkIGluY2x1ZGUgTGVnbz8sLCwsLCwsLCwsLCwsLA==")));              const text = preloadedCSV;              const parsed = parseCSV(text);                            const rowsByName = {};              let filterStart = -1;              parsed.forEach((rc, i) => {                 if (rc && rc.length > 0 && rc[0]) rowsByName[rc[0]] = rc;                 if (rc && rc.length > 0 && rc[0] === 'Filter buttons') filterStart = i;              });                            const cols = [];              if(rowsByName['Roundel text']) {                const headerRow = rowsByName['Roundel text'];                for(let col = 1; col < headerRow.length; col++) {                   let label = headerRow[col];                   if (!label) continue;                                      let q = rowsByName['Search Query'] && rowsByName['Search Query'][col] ? rowsByName['Search Query'][col] : '';                   let img = rowsByName['Roundel image'] && rowsByName['Roundel image'][col] ? rowsByName['Roundel image'][col] : '';                   let ds = rowsByName['Discount Amount'] && rowsByName['Discount Amount'][col] ? rowsByName['Discount Amount'][col] : '';                   let pr = rowsByName['Price Range'] && rowsByName['Price Range'][col] ? rowsByName['Price Range'][col] : '';                   let rt = rowsByName['Retailer'] && rowsByName['Retailer'][col] ? rowsByName['Retailer'][col] : '';                   let ot = rowsByName['Offer Type'] && rowsByName['Offer Type'][col] ? rowsByName['Offer Type'][col] : '';                                      let filters = [];                   if(filterStart > 0) {                     for(let r = filterStart + 1; r < parsed.length; r++) {                         if(!parsed[r] || parsed[r][0] === 'Notes' || parsed[r][0] === 'Categories to consider') break;                         let f = parsed[r][col];                         if(f) filters.push(f);                     }                   }                   cols.push({ label, img, q, ds, pr, rt, ot, filters });                }              }              this.carouselData = cols;              if (this.carouselData && this.carouselData.length > 0) {                 const isMatched = this.carouselData.some(c => c.q === this.currentQuery || c.label === this.currentQuery);                 if (!isMatched) {                    const first = this.carouselData[0];                    this.currentQuery = first.q || first.label;                    if (this.priceFilter) this.priceFilter.value = 'all';                    if (this.customPriceMin) this.customPriceMin.value = '';                    if (this.customPriceMax) this.customPriceMax.value = '';                    let dPr = first.pr || 'all';                    if (typeof dPr === 'string' && dPr !== 'all') {                       let prLower = dPr.toLowerCase();                       if (prLower.includes('min') || prLower.includes('over')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else if (prLower.includes('max') || prLower.includes('under')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       }                    }                    let dAm = '0';                    if(first.ds && typeof first.ds === 'string') {                       let m = first.ds.match(/(\d+)/);                       if(m) dAm = m[1];                    }                    if (this.discountFilter) this.discountFilter.value = dAm;                    if (this.offerTypeSelect) this.offerTypeSelect.value = first.ot || '';                    if (this.retailerSelect) this.retailerSelect.value = first.rt || '';                    this.selectedBrands = [];                    if (this.brandDropdown) {                        const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                        chks.forEach(chk => chk.checked = false);                    }                    if (this.searchInput) this.searchInput.value = this.currentQuery;                 }              }              this.renderCarouselUI();          } catch(e){ console.warn(e); }        }                renderCarouselUI() {           const roundelWrapper = this.root.querySelector('.tg-df-carousel-roundels');           if(!roundelWrapper || !this.carouselData) return;                      let html = '';           this.carouselData.forEach(r => {              const q = r.q || r.label;              const isActive = (this.currentQuery === q || this.currentQuery === r.label) ? 'active' : '';              const imgHtml = r.img ? `\x3Cimg src="${r.img}" alt="${r.label}" />` : `\x3Csvg width="32" height="32" fill="#1F69FF" viewBox="0 0 24 24">\x3Cpath d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/>\x3C/svg>`;              html += `                \x3Cdiv class="tg-df-roundel tg-df-carousel-cat ${isActive}" data-label="${this.escapeHTML(r.label)}">                  \x3Cdiv class="tg-df-roundel-img-box">${imgHtml}\x3C/div>                  \x3Cspan class="tg-df-roundel-label">${this.escapeHTML(r.label)}\x3C/span>                \x3C/div>              `;           });           roundelWrapper.innerHTML = html;                      // Rebind clicks           const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');           roundels.forEach(rNode => {             rNode.addEventListener('click', () => {                const r = this.carouselData.find(c => c.label === rNode.getAttribute('data-label'));                 if(!r) return;                                  if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: r.label,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = r.q || r.label;                const labelTitle = this.root.querySelector('#tg-df-carousel-title-label');                if (labelTitle) labelTitle.textContent = 'Best ' + this.currentQuery;                if (this.priceFilter) this.priceFilter.value = 'all';                if (this.customPriceMin) this.customPriceMin.value = '';                if (this.customPriceMax) this.customPriceMax.value = '';                let dPr = r.pr || 'all';                if (typeof dPr === 'string' && dPr !== 'all') {                   let prLower = dPr.toLowerCase();                   if (prLower.includes('min') || prLower.includes('over')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMin) this.customPriceMin.value = m[1];                   } else if (prLower.includes('max') || prLower.includes('under')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMax) this.customPriceMax.value = m[1];                   }                }                                let discountAmount = '0';                if(r.ds && typeof r.ds === 'string') {                   let m = r.ds.match(/(\d+)/);                   if(m) discountAmount = m[1];                }                if (this.discountFilter) this.discountFilter.value = discountAmount;                if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                                // Clear brands                    this.selectedBrands = [];                    if (this.brandDropdown) {                    const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                    chks.forEach(chk => chk.checked = false);                }                                if (this.searchInput) this.searchInput.value = this.currentQuery;                                roundels.forEach(ro => ro.classList.remove('active'));                if (rNode) rNode.classList.add('active');                                this.renderCarouselFilters(r);                this.fetchDeals(this.currentQuery);             });           });                      // Auto-highlight active           const activeR = this.carouselData.find(c => c.q === this.currentQuery || c.label === this.currentQuery);           if(activeR) this.renderCarouselFilters(activeR);        }                renderCarouselFilters(r) {           const filtersWrap = this.root.querySelector('.tg-df-carousel-filters-wrap');           if(!filtersWrap) return;                      let html = `\x3Cbutton class="tg-df-carousel-filter-btn" data-type="all">All\x3C/button>`;                      r.filters.forEach(f => {              let fL = f.toLowerCase();              let icon = '';              let logic = `data-type="custom" data-v="${this.escapeHTML(f)}"`;              if (fL === 'amazon deals' || fL === 'prime deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>`;              } else if (fL === 'lightning deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>`;              } else {                 if (fL.includes('lightning')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-zap">\x3Cpolygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2">\x3C/polygon>\x3C/svg>`;                 } else if (fL.includes('% off')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>`;                 } else if (fL.includes('under') || fL.includes('min ')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>`;                 }                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>${icon} ${this.escapeHTML(f)}\x3C/button>`;              }           });                      filtersWrap.innerHTML = html;                      const btns = filtersWrap.querySelectorAll('button');           btns.forEach(b => {             b.addEventListener('click', () => {                const type = b.getAttribute('data-type');                if (type === 'custom') {                   const v = b.getAttribute('data-v');                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-custom-${(v||'').toLowerCase().replace(/[^a-z0-9]+/g, '-')}`, name: 'Custom Filter', label: v });                }                if (type === 'all') {                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: 'filter-clear-all', name: 'Clear all', label: 'Clear all filters' });                   // reset everything                   btns.forEach(btn => btn.classList.remove('active'));                   b.classList.add('active');                                      // Reset prices                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   if (this.brandDropdown) {                     const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                     chks.forEach(chk => chk.checked = false);                   }                } else {                   const v = b.getAttribute('data-v');                   const fL = v.toLowerCase();                                      let mapRet = ['amazon', 'walmart', 'best buy', 'target', 'john lewis', 'currys', 'argos'];                   const getCategory = (s) => {                      if (s === 'lightning deals' || s === 'amazon deals' || s === 'prime deals') return 'offer';                      if (s.includes('% off')) return 'discount';                      if (s.includes('under') || s.includes('over') || s.includes('min') || s.includes('max')) return 'price';                      if (mapRet.includes(s)) return 'retailer';                      return 'brand';                   };                   const cat = getCategory(fL);                   const wasActive = b.classList.contains('active');                   if (cat !== 'brand') {                      btns.forEach(btn => {                          if (btn === b) return;                          if (btn.getAttribute('data-type') === 'all') return;                          const bV = btn.getAttribute('data-v');                          if (!bV) return;                          if (getCategory(bV.toLowerCase()) === cat) btn.classList.remove('active');                      });                   }                   if (wasActive) b.classList.remove('active');                   else b.classList.add('active');                   let anyActive = Array.from(btns).some(btn => btn !== btns[0] && btn.classList.contains('active'));                   if (!anyActive) {                       btns[0].click();                       return;                   } else {                       btns[0].classList.remove('active');                   }                                      if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   btns.forEach(btn => {                       if (!btn.classList.contains('active') || btn.getAttribute('data-type') === 'all') return;                       const vv = btn.getAttribute('data-v');                       const vl = vv.toLowerCase();                                              if (vl === 'lightning deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_lightning';                       } else if (vl === 'amazon deals' || vl === 'prime deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_prime';                       } else if (vl.includes('% off')) {                          let m = vl.match(/(\d+)%/);                          if (m && this.discountFilter) this.discountFilter.value = m[1];                       } else if (vl.includes('under') || vl.includes('max')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       } else if (vl.includes('min') || vl.includes('over')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else {                          let foundR = mapRet.find(x => x === vl);                          if (foundR) {                             let realR = ['Amazon', 'Walmart', 'Best Buy', 'Target', 'John Lewis', 'Currys', 'Argos'].find(x => x.toLowerCase() === vl);                             if (this.retailerSelect) this.retailerSelect.value = realR;                          } else {                             this.selectedBrands.push(vv);                          }                       }                   });                                      if (this.brandDropdown) {                       const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                       chks.forEach(c => c.checked = this.selectedBrands.includes(c.value));                   }                                      if (r.pr && typeof r.pr === 'string') {                       let prL = r.pr.toLowerCase();                       if (prL.includes('under $')) {                           let m = prL.match(/under \$(\d+)/i);                           if (m && this.customPriceMax && !this.customPriceMax.value) this.customPriceMax.value = m[1];                       }                   }                }                                this.fetchDeals(this.currentQuery);             });           });                      // default to highlighting first           btns[0].classList.add('active');        }async fetchDeals(query, append = false) {          if (!append) {             this.showLoading();             this.deals = [];             this.displayLimit = this.getRowsLimit();          } else {             this.displayLimit += this.getRowsLimit();          }                    try {            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad(append);            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query, append);               } else {                 await this.fetchHawkDeals(query, append);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query, append);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const url = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let dynamicBrandsCounts = {};                    targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                   dynamicBrandsCounts[data.brand] = (dynamicBrandsCounts[data.brand] || 0) + 1;                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || ''                });             });          });                    const airedaleBrandsList = Object.keys(dynamicBrandsCounts).map(b => ({              formatted_value: b,              count: dynamicBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query, append = false) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (append && this.deals.length > 0) {            url.searchParams.append('offset', this.deals.length.toString());          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : (this.getViewMode() === 'savings_squad' ? 'date_desc' : 'discount_desc');          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin-top:8px;">${_div}                ${_div}              ${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)} (${this.airedaleTagCounts[tag] || 0})${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = isSavingsSquadMode ? 'View Deal' : 'Check Price';              if (isSavingsSquadMode) {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                  ${_div}                `;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = `                \x3Cdiv class="tg-df-card-merchant-wrapper">                  \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                ${_div}                \x3Cdiv class="tg-df-card-price-group">                  ${isSavingsSquadMode ? '' : `                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                  `}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description">\x3Cp>${this.escapeHTML(deal.description)}${_p}${_div}` : ''}                      ${_div}                    ${_div}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>${deal.isCheckPrice ? 'Check Price' : 'View Deal'}${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cp style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 12px; line-height: 1.4;">${this.escapeHTML(deal.description)}${_p}` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${priceGroupHtml}                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta ${isSavingsSquadMode ? 'tg-df-cta-savings-squad' : ''}" style="text-decoration: none;">${ctaText}${_a}                  ${_div}                ${_div}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit || ((this.getViewMode() === 'carousel' || this.getViewMode() === 'auto') && displayDeals.length > 0 && displayDeals.length % ((this.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12) === 0)) {            if (this.getViewMode() === 'carousel') {               dealsHtml += `                 \x3Cbutton type="button" class="tg-df-load-more-card tg-df-load-more">                   \x3Csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-bottom: 8px;">\x3Cpath d="M5 12h14">\x3C/path>\x3Cpath d="m12 5 7 7-7 7">\x3C/path>\x3C/svg>                   Load More                 ${_button}               `;            } else {               dealsHtml += `                 \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                   \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer; display: flex; align-items: center;">Load More${_button}                 ${_div}               `;            }          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }                    let gridWrapper = this.grid.parentElement;          if (gridWrapper && gridWrapper.classList.contains('tg-df-grid-wrapper')) {             let rightChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-right');             let leftChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-left');             if (this.getViewMode() === 'carousel') {                 // The observer set up in setupScrollListeners handles visibility.                 if (rightChevron) rightChevron.style.display = 'flex';                 if (leftChevron) leftChevron.style.display = 'none'; // reset correctly             } else {                 if (rightChevron) rightChevron.style.display = 'none';                 if (leftChevron) leftChevron.style.display = 'none';             }          }                    const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', async () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              if (displayDeals.length <= this.displayLimit) {                 loadMoreBtn.innerHTML = `                  <svg class="tg-df-spinner" style="width: 16px; height: 16px; display: inline-block; vertical-align: middle; margin-right: 8px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" d="M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48l2.83-2.83"/></svg>                  Loading...                 `;                 loadMoreBtn.disabled = true;                 await this.fetchDeals(this.currentQuery, true);              } else {                 this.displayLimit += this.getRowsLimit();                 this.render();              }            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            setTimeout(() => {               if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');               document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));            }, 50);          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ A yoga instructor says these are the 4 exercises she'd start with to build full-body 'strength and grounding' this fall ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The changing seasons can really affect your mood, especially as we move from those long days and warm evenings of summer into the cozy fall season.</p><p>That's why your routine may need a switch-up, too. Maybe your body is craving a slower approach, or you just want to try something new. To help you, <a href="https://cmbpublicity-com.jmailroute.net/x/d?c=53820816&amp;l=e5a1a3ff-de69-4374-9304-a812eec62988&amp;r=3d41127e-478f-45d9-8474-daf38e366e98" target="_blank">YogaRenew</a> instructor <a href="https://cmbpublicity-com.jmailroute.net/x/d?c=53820816&amp;l=4b4c9b50-7bee-41fd-a5f5-369471f1ef3b&amp;r=3d41127e-478f-45d9-8474-daf38e366e98" target="_blank">Melie Purdon</a> shares four yoga poses to help you feel grounded, energized and present as the weather cools.</p><p>Wherever you choose to practice, these poses will help you feel calm, centered and ready to welcome the crisp fall air. This short routine is beginner-friendly and low-impact, which means you can build foundational strength while putting less stress and strain on your joints.</p><p>One of the <a href="https://www.tomsguide.com/best-picks/best-yoga-mats">best yoga mats</a> is also recommended, and that's all. </p><h2 id="five-yoga-poses-for-grounding-strength-and-calm">Five yoga poses for grounding, strength and calm</h2><p>Yoga <a href="https://www.tomsguide.com/wellness/workouts/use-this-10-minute-mobility-routine-to-boost-your-flexibility-and-improve-posture-no-equipment-needed">improves mobility and flexibility </a>and strengthens your body using your body weight and some props like blocks and straps. It helps shift your body into the parasympathetic nervous system, which can reduce stress and anxiety and boost relaxation.</p><p>As the seasons change, particularly from summer to fall, grounding practices can help you manage the transition more seamlessly, especially if you find yourself sensitive to this.</p><p>Yoga is unlikely to<a href="https://www.tomsguide.com/features/progressive-overload-what-is-it-and-how-does-it-help-build-muscle-and-strength"> overload the muscles </a>in a way that builds maximal strength and muscle (you'd need to consider lifting weights several times per week), but it improves <a href="https://www.tomsguide.com/wellness/workouts/undesk-your-hips-and-build-functional-strength-with-this-3-move-pilates-glute-workout">functional strength</a> without weights and helps maintain healthy muscles, bones, joints and ligaments.</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 from your physician or a yoga instructor before starting these exercises.</em></p><h3 class="article-body__section" id="section-1-revolved-triangle"><span>1. Revolved triangle</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:1440px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="6JFuFZwv7JfSwj7EHrGkVK" name="Revolved triangle" alt="Purdon showing revolved triangle pose on yoga mat" src="https://cdn.mos.cms.futurecdn.net/6JFuFZwv7JfSwj7EHrGkVK-1920-80.jpg" mos="" align="middle" fullscreen="" width="1440" height="810" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: CMB Publicity)</span></figcaption></figure><p><strong>Benefits: </strong>"Twists are inherently invigorating, combining strong legs, spinal extension, and torso rotation to help you feel awake and energized," says Purdon. "It's the perfect pairing with crisp fall air, especially when practicing outdoors and taking in the changing scenery."</p><ul><li>Stand with your legs wide apart, turning your right foot outward and your left foot slightly inward.</li><li>Extend your arms to shoulder height, then hinge forward over your right leg.</li><li>Place your left hand on the outside of your right shin or on a block, and rotate your torso to the right, reaching your right arm toward the ceiling.</li><li>Keep your spine long and your legs firm.</li><li>Hold for 2–3 breaths, then return to center and repeat on the opposite side.</li></ul><h3 class="article-body__section" id="section-2-wide-leg-forward-fold"><span>2. Wide-leg forward fold</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:1440px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4s8z5bQSUsyvX772uTjpVK" name="Wide leg fold" alt="Purdon showing wide legged forward fold on yoga mat" src="https://cdn.mos.cms.futurecdn.net/4s8z5bQSUsyvX772uTjpVK-1920-80.jpg" mos="" align="middle" fullscreen="" width="1440" height="810" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: CMB Publicity)</span></figcaption></figure><p><strong>Benefits: </strong>"This forward fold combines strong, active legs with a quiet head, offering a chance to slow down while keeping your body engaged," Purdon says. "Between work, apple picking, school schedules, and Halloween costume crafting, sometimes the best way to reset is to give your body something specific to focus on."</p><ul><li>Stand with your feet wide apart and parallel, pressing evenly through the outer edges of your feet.</li><li>Place your hands on your hips, lift your chest, and fold forward from the hips.</li><li>Bring your fingertips or palms to the floor, keeping your arms straight and your chest extended.</li><li>If your flexibility allows, lower the crown of your head toward the floor without collapsing into your neck.</li><li>Keep your legs active and your weight evenly distributed through your feet.</li></ul><h3 class="article-body__section" id="section-3-headstand"><span>3. Headstand</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:1440px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="anjoBZMKn3VRfFQzzNa7RK" name="Headstand" alt="Purdon showing headstand on yoga mat" src="https://cdn.mos.cms.futurecdn.net/anjoBZMKn3VRfFQzzNa7RK-1920-80.jpg" mos="" align="middle" fullscreen="" width="1440" height="810" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: CMB Publicity)</span></figcaption></figure><p><strong>Benefits: </strong>"Often called the 'King of Asanas,' headstand demands full concentration and can leave experienced practitioners feeling focused and invigorated. The combination of balance, stability, and a completely different perspective makes it a powerful way to reconnect with the present moment," says Purdon.</p><p>"Practice this advanced pose with guidance from a qualified yoga teacher rather than relying on written instructions alone."</p><p>This is the only exercise that isn't beginner-friendly, but you can still play around with it while keeping your feet firmly on the ground to get benefits and stay playful. </p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="vGnNDN" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><ul><li>Interlace your fingers and place your forearms on the floor, keeping your elbows shoulder-width apart and your hands in a U-shape rather than a V.</li><li>Rest the crown of your head on the floor, supported by your cupped hands, and press firmly through your forearms, lifting your shoulders.</li><li>Curl your toes under, lift your knees, and walk your feet toward your head.</li><li>If you're experienced, raise one leg at a time or lift both legs toward the ceiling, keeping them firm and active.</li><li>Lower slowly and with control.</li></ul><h3 class="article-body__section" id="section-4-supported-bridge"><span>4. Supported bridge </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:1370px;"><p class="vanilla-image-block" style="padding-top:56.50%;"><img id="QL7yabgEEZJDpTpKGuYNNK" name="Supported bridge" alt="Purdon showing supported bridge pose on yoga mat" src="https://cdn.mos.cms.futurecdn.net/QL7yabgEEZJDpTpKGuYNNK-1920-80.jpg" mos="" align="middle" fullscreen="" width="1370" height="774" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: CMB Publicity)</span></figcaption></figure><p><strong>Benefits: </strong>"Supported bridge opens the front of the body and offers a moment of relief from the tension that builds up after hours of sitting, working, and running around," Purdon explains. "With the block supporting your sacrum, you can ease into stillness without having to hold yourself up. </p><p>"If you're practicing outdoors, take a few minutes to enjoy the changing leaves and let the demands of the day fade into the background."</p><ul><li>Lie on your back with your knees bent and feet flat on the floor, hip-width apart.</li><li>Press into your feet to lift your hips, then place a yoga block beneath your sacrum.</li><li>Relax into the support, keeping your feet grounded or extending your legs toward the ceiling if comfortable and appropriate for your practice.</li><li>Breathe comfortably for 3–5 minutes.</li><li>To release, lift your hips slightly to remove the block, and slowly lower your spine to the floor.</li></ul><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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><strong></strong><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"><strong>I teach people how to be more mobile: 3 low-impact back and shoulder moves that build stability and strength after 40</strong></a><strong></strong></li><li><strong></strong><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"><strong>According to a personal trainer, this exercise is 100 times more effective than crunches. I tried it and was humbled</strong></a><strong></strong></li><li><strong></strong><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"><strong>I teach people over 50 to be mobile: 3 low-impact moves that build more stability than a 30-minute walk</strong></a></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/workouts/a-yoga-instructor-says-these-are-the-4-exercises-shed-start-with-to-build-full-body-strength-and-grounding-this-fall</link>
                                                                            <description>
                            <![CDATA[ Build strength and boost your yoga practice this fall with these four low-impact exercises that ground your body. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">nbv7XKCpP747yCw8cu2oWa</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/rPLV5vgzMuE7MPuiYCSw98-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 18 Oct 2026 08:30:00 +0000</pubDate>                                                                                                                                <updated>Sun, 18 Oct 2026 12:34:42 +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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/rPLV5vgzMuE7MPuiYCSw98-1920-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[woman doing yoga stretch]]></media:description>                                                            <media:text><![CDATA[woman doing yoga stretch]]></media:text>
                                <media:title type="plain"><![CDATA[woman doing yoga stretch]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/rPLV5vgzMuE7MPuiYCSw98-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The changing seasons can really affect your mood, especially as we move from those long days and warm evenings of summer into the cozy fall season.</p><p>That's why your routine may need a switch-up, too. Maybe your body is craving a slower approach, or you just want to try something new. To help you, <a href="https://cmbpublicity-com.jmailroute.net/x/d?c=53820816&amp;l=e5a1a3ff-de69-4374-9304-a812eec62988&amp;r=3d41127e-478f-45d9-8474-daf38e366e98" target="_blank">YogaRenew</a> instructor <a href="https://cmbpublicity-com.jmailroute.net/x/d?c=53820816&amp;l=4b4c9b50-7bee-41fd-a5f5-369471f1ef3b&amp;r=3d41127e-478f-45d9-8474-daf38e366e98" target="_blank">Melie Purdon</a> shares four yoga poses to help you feel grounded, energized and present as the weather cools.</p><p>Wherever you choose to practice, these poses will help you feel calm, centered and ready to welcome the crisp fall air. This short routine is beginner-friendly and low-impact, which means you can build foundational strength while putting less stress and strain on your joints.</p><p>One of the <a href="https://www.tomsguide.com/best-picks/best-yoga-mats">best yoga mats</a> is also recommended, and that's all. </p><h2 id="five-yoga-poses-for-grounding-strength-and-calm">Five yoga poses for grounding, strength and calm</h2><p>Yoga <a href="https://www.tomsguide.com/wellness/workouts/use-this-10-minute-mobility-routine-to-boost-your-flexibility-and-improve-posture-no-equipment-needed">improves mobility and flexibility </a>and strengthens your body using your body weight and some props like blocks and straps. It helps shift your body into the parasympathetic nervous system, which can reduce stress and anxiety and boost relaxation.</p><p>As the seasons change, particularly from summer to fall, grounding practices can help you manage the transition more seamlessly, especially if you find yourself sensitive to this.</p><p>Yoga is unlikely to<a href="https://www.tomsguide.com/features/progressive-overload-what-is-it-and-how-does-it-help-build-muscle-and-strength"> overload the muscles </a>in a way that builds maximal strength and muscle (you'd need to consider lifting weights several times per week), but it improves <a href="https://www.tomsguide.com/wellness/workouts/undesk-your-hips-and-build-functional-strength-with-this-3-move-pilates-glute-workout">functional strength</a> without weights and helps maintain healthy muscles, bones, joints and ligaments.</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 from your physician or a yoga instructor before starting these exercises.</em></p><h3 class="article-body__section" id="section-1-revolved-triangle"><span>1. Revolved triangle</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:1440px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="6JFuFZwv7JfSwj7EHrGkVK" name="Revolved triangle" alt="Purdon showing revolved triangle pose on yoga mat" src="https://cdn.mos.cms.futurecdn.net/6JFuFZwv7JfSwj7EHrGkVK-1920-80.jpg" mos="" align="middle" fullscreen="" width="1440" height="810" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: CMB Publicity)</span></figcaption></figure><p><strong>Benefits: </strong>"Twists are inherently invigorating, combining strong legs, spinal extension, and torso rotation to help you feel awake and energized," says Purdon. "It's the perfect pairing with crisp fall air, especially when practicing outdoors and taking in the changing scenery."</p><ul><li>Stand with your legs wide apart, turning your right foot outward and your left foot slightly inward.</li><li>Extend your arms to shoulder height, then hinge forward over your right leg.</li><li>Place your left hand on the outside of your right shin or on a block, and rotate your torso to the right, reaching your right arm toward the ceiling.</li><li>Keep your spine long and your legs firm.</li><li>Hold for 2–3 breaths, then return to center and repeat on the opposite side.</li></ul><h3 class="article-body__section" id="section-2-wide-leg-forward-fold"><span>2. Wide-leg forward fold</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:1440px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4s8z5bQSUsyvX772uTjpVK" name="Wide leg fold" alt="Purdon showing wide legged forward fold on yoga mat" src="https://cdn.mos.cms.futurecdn.net/4s8z5bQSUsyvX772uTjpVK-1920-80.jpg" mos="" align="middle" fullscreen="" width="1440" height="810" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: CMB Publicity)</span></figcaption></figure><p><strong>Benefits: </strong>"This forward fold combines strong, active legs with a quiet head, offering a chance to slow down while keeping your body engaged," Purdon says. "Between work, apple picking, school schedules, and Halloween costume crafting, sometimes the best way to reset is to give your body something specific to focus on."</p><ul><li>Stand with your feet wide apart and parallel, pressing evenly through the outer edges of your feet.</li><li>Place your hands on your hips, lift your chest, and fold forward from the hips.</li><li>Bring your fingertips or palms to the floor, keeping your arms straight and your chest extended.</li><li>If your flexibility allows, lower the crown of your head toward the floor without collapsing into your neck.</li><li>Keep your legs active and your weight evenly distributed through your feet.</li></ul><h3 class="article-body__section" id="section-3-headstand"><span>3. Headstand</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:1440px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="anjoBZMKn3VRfFQzzNa7RK" name="Headstand" alt="Purdon showing headstand on yoga mat" src="https://cdn.mos.cms.futurecdn.net/anjoBZMKn3VRfFQzzNa7RK-1920-80.jpg" mos="" align="middle" fullscreen="" width="1440" height="810" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: CMB Publicity)</span></figcaption></figure><p><strong>Benefits: </strong>"Often called the 'King of Asanas,' headstand demands full concentration and can leave experienced practitioners feeling focused and invigorated. The combination of balance, stability, and a completely different perspective makes it a powerful way to reconnect with the present moment," says Purdon.</p><p>"Practice this advanced pose with guidance from a qualified yoga teacher rather than relying on written instructions alone."</p><p>This is the only exercise that isn't beginner-friendly, but you can still play around with it while keeping your feet firmly on the ground to get benefits and stay playful. </p><figure class="inline-layout"><div style="min-height: 400px;"><fw-embed-feed channel="toms_guide" playlist="vGnNDN" mode="row" player_placement="bottom-right"></fw-embed-feed></div></figure><ul><li>Interlace your fingers and place your forearms on the floor, keeping your elbows shoulder-width apart and your hands in a U-shape rather than a V.</li><li>Rest the crown of your head on the floor, supported by your cupped hands, and press firmly through your forearms, lifting your shoulders.</li><li>Curl your toes under, lift your knees, and walk your feet toward your head.</li><li>If you're experienced, raise one leg at a time or lift both legs toward the ceiling, keeping them firm and active.</li><li>Lower slowly and with control.</li></ul><h3 class="article-body__section" id="section-4-supported-bridge"><span>4. Supported bridge </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:1370px;"><p class="vanilla-image-block" style="padding-top:56.50%;"><img id="QL7yabgEEZJDpTpKGuYNNK" name="Supported bridge" alt="Purdon showing supported bridge pose on yoga mat" src="https://cdn.mos.cms.futurecdn.net/QL7yabgEEZJDpTpKGuYNNK-1920-80.jpg" mos="" align="middle" fullscreen="" width="1370" height="774" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: CMB Publicity)</span></figcaption></figure><p><strong>Benefits: </strong>"Supported bridge opens the front of the body and offers a moment of relief from the tension that builds up after hours of sitting, working, and running around," Purdon explains. "With the block supporting your sacrum, you can ease into stillness without having to hold yourself up. </p><p>"If you're practicing outdoors, take a few minutes to enjoy the changing leaves and let the demands of the day fade into the background."</p><ul><li>Lie on your back with your knees bent and feet flat on the floor, hip-width apart.</li><li>Press into your feet to lift your hips, then place a yoga block beneath your sacrum.</li><li>Relax into the support, keeping your feet grounded or extending your legs toward the ceiling if comfortable and appropriate for your practice.</li><li>Breathe comfortably for 3–5 minutes.</li><li>To release, lift your hips slightly to remove the block, and slowly lower your spine to the floor.</li></ul><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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><strong></strong><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"><strong>I teach people how to be more mobile: 3 low-impact back and shoulder moves that build stability and strength after 40</strong></a><strong></strong></li><li><strong></strong><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"><strong>According to a personal trainer, this exercise is 100 times more effective than crunches. I tried it and was humbled</strong></a><strong></strong></li><li><strong></strong><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"><strong>I teach people over 50 to be mobile: 3 low-impact moves that build more stability than a 30-minute walk</strong></a></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ This is exactly what ditching stretching for this 5-move mobility routine can do for your body ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Ah, <a href="https://www.tomsguide.com/wellness/fitness/im-a-personal-trainer-3-things-i-wish-i-had-known-about-stretching-and-mobility-when-i-started-exercising">stretching versus mobility</a>. It's a debate that never ends. As a coach who focuses most of my time on teaching mobility classes to people of all ages, I am a little biased, but I can tell you that while stretching <em>can</em> be beneficial (certain types, and when done properly, for muscle flexibility), mobility training will move the needle most for anti-aging and joint health.</p><p>I recently put together this 20-minute mobility routine you can do at home using the <a href="https://www.tomsguide.com/best-picks/best-yoga-mats">best yoga mat</a> and your bodyweight. You don't need equipment, but bands and light weights are optional; it depends on how much experience you already have with the movements. </p><p>Check out the moves below and what you can expect from your body over time.</p><h2 id="five-move-mobility-routine-from-a-coach">Five-move mobility routine from a coach</h2><p>As you age, strong bones, muscles, and ligaments help you stay active, whether that's gardening, playing with your kids (and grandkids), hitting the gym, or running the track.</p><p>I encourage at least two strength sessions per week, along with daily mobility work, even if that means a bodyweight or calisthenics routine rather than lifting heavy weights. </p><p>Below are five exercises I swear by.</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><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/DehasbGIwcP/" target="_blank">A post shared by Tom's Guide Fitness | Workout Tips &amp; Gear (@tomsguidefitness)</a></p><p>A photo posted by </p></blockquote></div><ul><li><strong>Figure-4 deadlifts: </strong>Stand with a box, bench, or similar object to your left side. Position the outer side of your right foot on the top edge of the box and draw your right knee down, squaring your hips to create a figure-4 shape. Hold a weight using both hands. Hinge forward at your hips, send your butt back and lower the weight through the gap between your legs, as if performing a deadlift. Your back should be straight and shoulders drawn back, core active. Lower as far as you can until you feel a deep stretch in your glutes, hips and hamstrings, then drive upward to stand. <strong>6-8 reps, 2 sets, change sides.</strong></li><li><strong>Dynamic lunges</strong>: Stand with your front foot on a chair or box and your other leg extended behind you in a high lunge. Square your hips. Press your front knee forward over your toes and lean into the stretch as you raise both arms overhead. Return to the starting position. <strong>6-8 reps, 2 sets, change sides.</strong></li><li><strong>Banded martini glass:</strong> Stand with your feet hip-width apart and hold a band overhead slightly wider than shoulder-width apart. Keep your pelvis tucked in and core engaged. Avoid arching your lower back or flaring your ribs. Pull the band apart and draw your elbows down, allowing the band to pass behind you. Pause at the bottom to hold tension, then release to your starting position. <strong>6-8 reps, 2 sets.</strong></li><li><strong>Bulgarian split squat into Cossack squat: </strong>Stand with your back foot elevated on a bench or similar, with the top of the foot pressing down. Keep your hips square with a soft bend in your front knee. Bend your knees and lower into the split squat, drawing your back knee toward the bench behind you. Lean slightly forward as you do. Drive up to stand, transfer your weight into your back foot and turn to the side. Bend into a side lunge over the chair, pause, then turn to face the front of the room and repeat your split squat. <strong>6-8 reps, 2 sets, change sides.</strong></li><li><strong>Tabletop reverse flies:</strong> Start on your hands and knees, shoulders over wrists, hips over knees. Hold a light weight in your right hand. Press through your left hand, then sweep your right arm out to the side, like a bird flapping its wing; keep a soft bend in your elbow. Avoid rotating to the side or swinging your weight. <strong>6-8 reps, 2 sets, then change sides.</strong></li></ul><h2 id="why-these-5-exercises">Why these 5 exercises?</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="sdnYpriNKkvJxpP3H6tNzb" name="shutterstock_2813963563 mobility" alt="Woman in athletic wear stretching on a yoga mat outdoors in a lunge position" src="https://cdn.mos.cms.futurecdn.net/sdnYpriNKkvJxpP3H6tNzb-1920-80.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: Shutterstock)</span></figcaption></figure><p>Unlike building maximal strength or muscle, these five exercises prioritize movement over intensity. That doesn't mean they should feel easy; as always, growth comes from feeling uncomfortable and challenged, but you don't need to max out every rep here. </p><p>Start with resistance that lets you stay in control. That could mean using a more stable surface or just going easy on the weights. You might opt not to use weights at all, depending on how open your joints are and how much range of motion you have (range of motion is the amount of movement available around a joint).</p><p>Each of these moves has a different focus, so let's briefly discuss them. </p><ul><li><strong>Figure-4 deadlifts </strong>will activate the muscles along the back of your body while strengthening your hips, groin and glutes. The figure-4 leg position opens your hips statically, while hinging at the hips focuses on active range of motion.</li><li><strong>Dynamic lunges</strong> are great for warming up the lower body while stretching your hip flexors and improving ankle mobility. The raised position feels more accessible for many and allows you to sit lower into the lunge, while raising your arms overhead opens the upper body, shoulders and chest.</li><li><strong>The martini glass</strong> is a classic shoulder opener and challenges your arms, back, and to some degree, your upper chest. It's one of my favorite ways to prep for upper-body movements that involve lifting overhead while activating your back muscles.</li><li><strong>Bulgarian's</strong> are a classic leg-day staple and can be adapted by leaning slightly forward to challenge your glutes more. They build strength and muscle, and you'll notice a deep stretch down the hip and quad of your raised back leg. As you twist into your<strong> Cossack squat,</strong> notice a strong stretch down the adductors (inner thighs) and more ankle activation.</li><li><strong>Rear flies </strong>activate your rear shoulders and upper back. In the tabletop position, you can't swing the weight or use any momentum. Instead, use full control and squeeze at the top. Keep your hips square and core active, and you'll really feel this one in your shoulders.</li></ul><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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/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> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/workouts/this-is-exactly-what-ditching-stretching-for-this-5-move-mobility-routine-can-do-for-your-body</link>
                                                                            <description>
                            <![CDATA[ A mobility routine featuring these five exercises can help you build a strong, mobile body without stretching. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">7NTD8aBZ6twtYBBAp3Knyi</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/uk3XjrGhcjWsUkMgXiMLTF-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 18 Oct 2026 08: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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/uk3XjrGhcjWsUkMgXiMLTF-1920-80.jpg">
                                                            <media:credit><![CDATA[Future/ Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Sam at home performing upward dog stretch during workout]]></media:description>                                                            <media:text><![CDATA[Sam at home performing upward dog stretch during workout]]></media:text>
                                <media:title type="plain"><![CDATA[Sam at home performing upward dog stretch during workout]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/uk3XjrGhcjWsUkMgXiMLTF-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Ah, <a href="https://www.tomsguide.com/wellness/fitness/im-a-personal-trainer-3-things-i-wish-i-had-known-about-stretching-and-mobility-when-i-started-exercising">stretching versus mobility</a>. It's a debate that never ends. As a coach who focuses most of my time on teaching mobility classes to people of all ages, I am a little biased, but I can tell you that while stretching <em>can</em> be beneficial (certain types, and when done properly, for muscle flexibility), mobility training will move the needle most for anti-aging and joint health.</p><p>I recently put together this 20-minute mobility routine you can do at home using the <a href="https://www.tomsguide.com/best-picks/best-yoga-mats">best yoga mat</a> and your bodyweight. You don't need equipment, but bands and light weights are optional; it depends on how much experience you already have with the movements. </p><p>Check out the moves below and what you can expect from your body over time.</p><h2 id="five-move-mobility-routine-from-a-coach">Five-move mobility routine from a coach</h2><p>As you age, strong bones, muscles, and ligaments help you stay active, whether that's gardening, playing with your kids (and grandkids), hitting the gym, or running the track.</p><p>I encourage at least two strength sessions per week, along with daily mobility work, even if that means a bodyweight or calisthenics routine rather than lifting heavy weights. </p><p>Below are five exercises I swear by.</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><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/DehasbGIwcP/" target="_blank">A post shared by Tom's Guide Fitness | Workout Tips &amp; Gear (@tomsguidefitness)</a></p><p>A photo posted by </p></blockquote></div><ul><li><strong>Figure-4 deadlifts: </strong>Stand with a box, bench, or similar object to your left side. Position the outer side of your right foot on the top edge of the box and draw your right knee down, squaring your hips to create a figure-4 shape. Hold a weight using both hands. Hinge forward at your hips, send your butt back and lower the weight through the gap between your legs, as if performing a deadlift. Your back should be straight and shoulders drawn back, core active. Lower as far as you can until you feel a deep stretch in your glutes, hips and hamstrings, then drive upward to stand. <strong>6-8 reps, 2 sets, change sides.</strong></li><li><strong>Dynamic lunges</strong>: Stand with your front foot on a chair or box and your other leg extended behind you in a high lunge. Square your hips. Press your front knee forward over your toes and lean into the stretch as you raise both arms overhead. Return to the starting position. <strong>6-8 reps, 2 sets, change sides.</strong></li><li><strong>Banded martini glass:</strong> Stand with your feet hip-width apart and hold a band overhead slightly wider than shoulder-width apart. Keep your pelvis tucked in and core engaged. Avoid arching your lower back or flaring your ribs. Pull the band apart and draw your elbows down, allowing the band to pass behind you. Pause at the bottom to hold tension, then release to your starting position. <strong>6-8 reps, 2 sets.</strong></li><li><strong>Bulgarian split squat into Cossack squat: </strong>Stand with your back foot elevated on a bench or similar, with the top of the foot pressing down. Keep your hips square with a soft bend in your front knee. Bend your knees and lower into the split squat, drawing your back knee toward the bench behind you. Lean slightly forward as you do. Drive up to stand, transfer your weight into your back foot and turn to the side. Bend into a side lunge over the chair, pause, then turn to face the front of the room and repeat your split squat. <strong>6-8 reps, 2 sets, change sides.</strong></li><li><strong>Tabletop reverse flies:</strong> Start on your hands and knees, shoulders over wrists, hips over knees. Hold a light weight in your right hand. Press through your left hand, then sweep your right arm out to the side, like a bird flapping its wing; keep a soft bend in your elbow. Avoid rotating to the side or swinging your weight. <strong>6-8 reps, 2 sets, then change sides.</strong></li></ul><h2 id="why-these-5-exercises">Why these 5 exercises?</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="sdnYpriNKkvJxpP3H6tNzb" name="shutterstock_2813963563 mobility" alt="Woman in athletic wear stretching on a yoga mat outdoors in a lunge position" src="https://cdn.mos.cms.futurecdn.net/sdnYpriNKkvJxpP3H6tNzb-1920-80.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: Shutterstock)</span></figcaption></figure><p>Unlike building maximal strength or muscle, these five exercises prioritize movement over intensity. That doesn't mean they should feel easy; as always, growth comes from feeling uncomfortable and challenged, but you don't need to max out every rep here. </p><p>Start with resistance that lets you stay in control. That could mean using a more stable surface or just going easy on the weights. You might opt not to use weights at all, depending on how open your joints are and how much range of motion you have (range of motion is the amount of movement available around a joint).</p><p>Each of these moves has a different focus, so let's briefly discuss them. </p><ul><li><strong>Figure-4 deadlifts </strong>will activate the muscles along the back of your body while strengthening your hips, groin and glutes. The figure-4 leg position opens your hips statically, while hinging at the hips focuses on active range of motion.</li><li><strong>Dynamic lunges</strong> are great for warming up the lower body while stretching your hip flexors and improving ankle mobility. The raised position feels more accessible for many and allows you to sit lower into the lunge, while raising your arms overhead opens the upper body, shoulders and chest.</li><li><strong>The martini glass</strong> is a classic shoulder opener and challenges your arms, back, and to some degree, your upper chest. It's one of my favorite ways to prep for upper-body movements that involve lifting overhead while activating your back muscles.</li><li><strong>Bulgarian's</strong> are a classic leg-day staple and can be adapted by leaning slightly forward to challenge your glutes more. They build strength and muscle, and you'll notice a deep stretch down the hip and quad of your raised back leg. As you twist into your<strong> Cossack squat,</strong> notice a strong stretch down the adductors (inner thighs) and more ankle activation.</li><li><strong>Rear flies </strong>activate your rear shoulders and upper back. In the tabletop position, you can't swing the weight or use any momentum. Instead, use full control and squeeze at the top. Keep your hips square and core active, and you'll really feel this one in your shoulders.</li></ul><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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/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[ I’m a personal trainer for seniors — this exercise should be a non-negotiable for anyone in their 40s ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Training for your senior years starts long before you hit 65. The sooner you start focusing on full body stability, proper balance, and maintaining good posture, the better.</p><p>That’s why I teach weighted dead bugs to all of my personal training clients in their 40’s. This exercise strengthens key muscles in your deep core responsible for protecting your pelvis and spine, keeping you upright and balanced, and supporting your whole body during movement. If these muscles are properly trained and conditioned, you’ll be better safeguarded against serious falls and injuries as you age.</p><p>Even if you’re a total beginner, weighted dead bugs can be easily modified for your fitness level. And if you’re more advanced, you’re in luck — there are plenty of ways to make this movement incredibly challenging, too.</p><p>Grab a pair of <a href="https://www.tomsguide.com/wellness/fitness/best-adjustable-dumbbells">dumbbells</a> and give weighted dead bugs a try. It’s an excellent move for any age group. </p><h3 class="article-body__section" id="section-how-to-do-weighted-dead-bugs"><span>How to do weighted dead bugs</span></h3><p>Speak with your doctor before starting any new exercise or workout program. They may caution against certain activities based on your personal health circumstances. </p><p>Weighted dead bugs are appropriate for most fitness levels, but if you’re a beginner, it’s crucial to learn proper exercise form. Consider meeting with a certified trainer for guidance and appropriate modification options, if necessary. Doing the exercise incorrectly can lead to pain or injury.</p><p>You’ll need a pair of light or moderately heavy dumbbells and a yoga mat for weighted dead bugs. A good weight will allow you to do all of the reps in a set without needing to rest, but will leave you feeling tired. </p><p>Start by doing one set of 10 reps. As you get stronger, increase to 12-15 reps. As you get stronger, add a set or two until you’re doing 2-3 sets of 12-15 reps. Core exercises are generally safe to do every day, but start off by doing weighted dead bugs 2-3 times per week and gradually work your way up. </p><p>Weighted dead bugs can be done on their own, as part of your existing core workout, or as a warm-up for other activities.</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="QUGhzoN2nBexqogyWvoCbP" name="dumbbell dead bug" alt="an illo of a woman doing a weighted dead bug" src="https://cdn.mos.cms.futurecdn.net/QUGhzoN2nBexqogyWvoCbP-1920-80.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 how to do them:</p><ul><li>Hold a dumbbell in each hand.</li><li>Lie on your back with your knees bent and feet flat on the floor.</li><li>Press the dumbbells above your shoulders.</li><li>Engage your core muscles.</li><li>Lift the knees to a tabletop position.</li><li>Lengthen your left leg towards the mat while extending your right arm behind you.</li><li>Pause briefly.</li><li>Lift your left leg and right arm back to the starting position.</li><li>Lengthen your right leg towards the mat while extending your left arm behind you.</li><li>Pause briefly.</li><li>Lift your right leg and left arm back to the starting position.</li><li>Continue alternating between your two sides for 10-15 reps.</li></ul><h3 class="article-body__section" id="section-benefits-of-weighted-dead-bugs"><span>Benefits of weighted dead bugs</span></h3><p>Weighted dead bugs target the transverse abdominis, which keeps our pelvis and spine stable as we move. It’s vital that this deep core muscle is strong so that our balance, posture, and even breathing patterns stay optimal. </p><p>This exercise also works the rectus abdominis (or “six-pack” muscles), internal and external obliques, pelvic floor, and, to a lesser degree, pecs. </p><p>While dead bugs can be done unweighted (and should be, if you’re just starting out), the addition of the weight places greater demand on the core muscles, resulting in further muscular adaptations and strength gains. </p><p>The act of moving opposite sides of the body at once can also improve overall coordination.</p><h3 class="article-body__section" id="section-modifications-for-weighted-dead-bugs"><span>Modifications for weighted dead bugs</span></h3><p>Truth be told, I never start my clients with weighted dead bugs. I always have them master the <a href="https://youtu.be/AHOFOyQyY7w?si=QClFuGdisRPdAMV6" target="_blank">standard form</a> before adding weight. Before you pick up any dumbbells, you should be able to do at least 10-12 unweighted dead bugs without feeling too much strain. </p><p>If unweighted dead bugs are difficult, you can split the exercise into lower- and upper-body portions. Lower and lift your left leg, then lower and lift your right arm. Complete all reps on one side before switching to the other. </p><p>You can also use a single dumbbell or a plate as an intermediate step. You’ll lower both arms and one leg at a time. </p><h3 class="article-body__section" id="section-progressions-for-weighted-dead-bugs"><span>Progressions for weighted dead bugs</span></h3><p>The easiest way to make weighted dead bugs more challenging is to use heavier dumbbells. However, going too heavy may put strain on your shoulders, so use caution when working with heavier dumbbells.</p><p>You can also perform the exercise with straight legs instead of in a tabletop position. This requires more effort and stabilization from the deep core. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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><strong></strong><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"><strong>I teach people how to be more mobile: 3 low-impact back and shoulder moves that build stability and strength after 40</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-how-to-be-strong-and-mobile-this-is-the-one-exercise-i-regret-ignoring-for-years" target="_blank"><strong>I teach people how to be strong and mobile: this is the one exercise I regret ignoring for years</strong></a><strong></strong></li><li><strong></strong><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"><strong>I teach people over 50 to be mobile: 3 low-impact moves that build more stability than a 30-minute walk</strong></a><strong></strong></li></ul> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/workouts/im-a-personal-trainer-for-seniors-this-exercise-should-be-a-non-negotiable-for-anyone-in-their-40s</link>
                                                                            <description>
                            <![CDATA[ Here's the exercise everyone in their 40s should be doing, according to our resident personal trainer ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">aVSUuWTLQ8jbPv8zmQ5p8k</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/jpEwiTqsWC5ZTSbo5WmA4M-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sun, 18 Oct 2026 05:00:00 +0000</pubDate>                                                                                                                                <updated>Sun, 18 Oct 2026 12:35:39 +0000</updated>
                                                                                                                                            <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-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ null ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/jpEwiTqsWC5ZTSbo5WmA4M-1920-80.jpg">
                                                            <media:credit><![CDATA[Shutterstock]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[a woman with abs]]></media:description>                                                            <media:text><![CDATA[a woman with abs]]></media:text>
                                <media:title type="plain"><![CDATA[a woman with abs]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/jpEwiTqsWC5ZTSbo5WmA4M-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Training for your senior years starts long before you hit 65. The sooner you start focusing on full body stability, proper balance, and maintaining good posture, the better.</p><p>That’s why I teach weighted dead bugs to all of my personal training clients in their 40’s. This exercise strengthens key muscles in your deep core responsible for protecting your pelvis and spine, keeping you upright and balanced, and supporting your whole body during movement. If these muscles are properly trained and conditioned, you’ll be better safeguarded against serious falls and injuries as you age.</p><p>Even if you’re a total beginner, weighted dead bugs can be easily modified for your fitness level. And if you’re more advanced, you’re in luck — there are plenty of ways to make this movement incredibly challenging, too.</p><p>Grab a pair of <a href="https://www.tomsguide.com/wellness/fitness/best-adjustable-dumbbells">dumbbells</a> and give weighted dead bugs a try. It’s an excellent move for any age group. </p><h3 class="article-body__section" id="section-how-to-do-weighted-dead-bugs"><span>How to do weighted dead bugs</span></h3><p>Speak with your doctor before starting any new exercise or workout program. They may caution against certain activities based on your personal health circumstances. </p><p>Weighted dead bugs are appropriate for most fitness levels, but if you’re a beginner, it’s crucial to learn proper exercise form. Consider meeting with a certified trainer for guidance and appropriate modification options, if necessary. Doing the exercise incorrectly can lead to pain or injury.</p><p>You’ll need a pair of light or moderately heavy dumbbells and a yoga mat for weighted dead bugs. A good weight will allow you to do all of the reps in a set without needing to rest, but will leave you feeling tired. </p><p>Start by doing one set of 10 reps. As you get stronger, increase to 12-15 reps. As you get stronger, add a set or two until you’re doing 2-3 sets of 12-15 reps. Core exercises are generally safe to do every day, but start off by doing weighted dead bugs 2-3 times per week and gradually work your way up. </p><p>Weighted dead bugs can be done on their own, as part of your existing core workout, or as a warm-up for other activities.</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="QUGhzoN2nBexqogyWvoCbP" name="dumbbell dead bug" alt="an illo of a woman doing a weighted dead bug" src="https://cdn.mos.cms.futurecdn.net/QUGhzoN2nBexqogyWvoCbP-1920-80.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 how to do them:</p><ul><li>Hold a dumbbell in each hand.</li><li>Lie on your back with your knees bent and feet flat on the floor.</li><li>Press the dumbbells above your shoulders.</li><li>Engage your core muscles.</li><li>Lift the knees to a tabletop position.</li><li>Lengthen your left leg towards the mat while extending your right arm behind you.</li><li>Pause briefly.</li><li>Lift your left leg and right arm back to the starting position.</li><li>Lengthen your right leg towards the mat while extending your left arm behind you.</li><li>Pause briefly.</li><li>Lift your right leg and left arm back to the starting position.</li><li>Continue alternating between your two sides for 10-15 reps.</li></ul><h3 class="article-body__section" id="section-benefits-of-weighted-dead-bugs"><span>Benefits of weighted dead bugs</span></h3><p>Weighted dead bugs target the transverse abdominis, which keeps our pelvis and spine stable as we move. It’s vital that this deep core muscle is strong so that our balance, posture, and even breathing patterns stay optimal. </p><p>This exercise also works the rectus abdominis (or “six-pack” muscles), internal and external obliques, pelvic floor, and, to a lesser degree, pecs. </p><p>While dead bugs can be done unweighted (and should be, if you’re just starting out), the addition of the weight places greater demand on the core muscles, resulting in further muscular adaptations and strength gains. </p><p>The act of moving opposite sides of the body at once can also improve overall coordination.</p><h3 class="article-body__section" id="section-modifications-for-weighted-dead-bugs"><span>Modifications for weighted dead bugs</span></h3><p>Truth be told, I never start my clients with weighted dead bugs. I always have them master the <a href="https://youtu.be/AHOFOyQyY7w?si=QClFuGdisRPdAMV6" target="_blank">standard form</a> before adding weight. Before you pick up any dumbbells, you should be able to do at least 10-12 unweighted dead bugs without feeling too much strain. </p><p>If unweighted dead bugs are difficult, you can split the exercise into lower- and upper-body portions. Lower and lift your left leg, then lower and lift your right arm. Complete all reps on one side before switching to the other. </p><p>You can also use a single dumbbell or a plate as an intermediate step. You’ll lower both arms and one leg at a time. </p><h3 class="article-body__section" id="section-progressions-for-weighted-dead-bugs"><span>Progressions for weighted dead bugs</span></h3><p>The easiest way to make weighted dead bugs more challenging is to use heavier dumbbells. However, going too heavy may put strain on your shoulders, so use caution when working with heavier dumbbells.</p><p>You can also perform the exercise with straight legs instead of in a tabletop position. This requires more effort and stabilization from the deep core. </p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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><strong></strong><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"><strong>I teach people how to be more mobile: 3 low-impact back and shoulder moves that build stability and strength after 40</strong></a><strong></strong></li><li><strong></strong><a href="https://www.tomsguide.com/wellness/workouts/i-teach-people-how-to-be-strong-and-mobile-this-is-the-one-exercise-i-regret-ignoring-for-years" target="_blank"><strong>I teach people how to be strong and mobile: this is the one exercise I regret ignoring for years</strong></a><strong></strong></li><li><strong></strong><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"><strong>I teach people over 50 to be mobile: 3 low-impact moves that build more stability than a 30-minute walk</strong></a><strong></strong></li></ul>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I ran 40 miles in the Brooks Ghost Amp, and I’d actually buy it over the Ghost 18 ]]></title>
                                                                                                <dc:content><![CDATA[ <p>The Brooks line-up now has more ghosts than an episode of Scooby-Doo, but if I were only going to keep one of the Ghost 18, Ghost Max 4 and Ghost Amp, it would definitely be the Amp.</p><p>It’s exactly the type of shoe Brooks needed to modernize the Ghost and its array of daily trainers, with the Ghost Amp livelier and more versatile than the various Ghosts and Glycerins you can buy.</p><p>I enjoyed using the shoe for daily runs at easy, steady paces, with the new DNA Hype midsole foam and improved forefoot rocker making the Ghost Amp feel smooth and energetic.</p><p>However, in its category, the Brooks Ghost Amp competes with some of the best running shoes available, and there are options I’d buy ahead of it, like the bouncier <a href="https://www.tomsguide.com/wellness/running/asics-novablast-6-review">Asics Novablast 6 </a>or the lighter <a href="https://www.tomsguide.com/wellness/running/puma-deviate-pure-nitro-review">Puma Deviate Pure Nitro</a>.</p><h2 class="article-body__section" id="section-brooks-ghost-amp-review-price-and-availability"><span>Brooks Ghost Amp review: Price and availability</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="CYemZ3bqXSyShoHrVuqoYg" name="Brooks Ghost Amp-3" alt="Brooks Ghost Amp" src="https://cdn.mos.cms.futurecdn.net/CYemZ3bqXSyShoHrVuqoYg-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Brooks Ghost Amp launched in July 2026 and costs $150 in the U.S. and £135 in the U.K., which is the same price as the <a href="https://www.tomsguide.com/wellness/running/brooks-ghost-18-review">Brooks Ghost 18</a>.</p><p>It’s a good value shoe that comes in at around the same price as many of the most popular daily trainers, including the Asics Novablast 6, <a href="https://www.tomsguide.com/wellness/running/nike-pegasus-42-review">Nike Pegasus 42</a> and <a href="https://www.tomsguide.com/wellness/running/hoka-clifton-11-review">Hoka Clifton 11</a>.</p><h2 class="article-body__section" id="section-brooks-ghost-amp-review-design-and-fit"><span>Brooks Ghost Amp review: Design and fit</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ieHfoCkEEUUph8y8ACR9eg" name="Brooks Ghost Amp-4" alt="Brooks Ghost Amp" src="https://cdn.mos.cms.futurecdn.net/ieHfoCkEEUUph8y8ACR9eg-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Ghost Amp is currently available in seven colors, including the light blue design I tested. There's a wide version as well as the standard, and I found it fit me well in my normal running shoe size.</p><p>One big difference between it and the Ghost 18 is that the Ghost Amp has a 6mm drop from heel to toe, instead of the Ghost’s traditional 10mm.</p><p>The stack height is 36mm at the heel and 30mm at the forefoot, so the Ghost Amp isn't as maxed out as many daily trainers these days, which have 40mm of foam or more at the heel.</p><p>It weighs 9.3oz in my US men’s size 10, which is 1.4oz lighter than the Ghost 18 in my size. It’s not a featherweight, but for a daily trainer with a padded upper and thick outsole, the Ghost Amp is impressively light.</p><h3 class="article-body__section" id="section-upper"><span>Upper</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="zyVWAr7HGfFaMHHw7A2cdg" name="Brooks Ghost Amp-5" alt="Brooks Ghost Amp" src="https://cdn.mos.cms.futurecdn.net/zyVWAr7HGfFaMHHw7A2cdg-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Ghost Amp’s upper is quite a thick knit material with plenty of padding around the collar and tongue. It has a stiff internal heel counter to add more support at the back of the shoe.</p><p>I prefer a more minimal upper myself, but the Ghost Amp was comfortable and held my foot securely during runs, and it retains the plush step-in feel expected of the Ghost and Glycerin lines.</p><h3 class="article-body__section" id="section-midsole"><span>Midsole</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ZsG2aPUq8gq3z8VvWYYWag" name="Brooks Ghost Amp-6" alt="Brooks Ghost Amp" src="https://cdn.mos.cms.futurecdn.net/ZsG2aPUq8gq3z8VvWYYWag-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Ghost Amp uses a new midsole foam called DNA Hype, which is a <a href="https://www.tomsguide.com/wellness/running/fantastic-foams-and-supercritical-science-why-running-shoes-have-improved-so-much-in-the-past-10-years-explained-by-an-expert-who-makes-them">supercritical material</a> made from a blend of PEBA and EVA foams. </p><p>It’s not as springy as the DNA Gold foam used in some Brooks shoes, which is made entirely of PEBA, but it’s livelier than the EVA midsole on the Ghost 18.</p><p>The Ghost Amp also introduces Brooks’ SpringRamp tech in the forefoot, which is a section of firmer foam designed to add more propulsion to your toe-offs.</p><h3 class="article-body__section" id="section-outsole"><span>Outsole</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="hEj4eLGj3RyByXXGSYVHZg" name="Brooks Ghost Amp-7" alt="Brooks Ghost Amp" src="https://cdn.mos.cms.futurecdn.net/hEj4eLGj3RyByXXGSYVHZg-1920-80.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>While it doesn’t have a full outsole, a thick layer of rubber covers most of the forefoot and heel on the Ghost Amp, and I have no concerns about its grip or durability after testing.</p><p>It’s not quite as thick and extensive an outsole as the Ghost 18, but the trade-off is worth it to have the lighter shoe, as there’s still plenty of rubber on the bottom of the Amp.</p><h2 class="article-body__section" id="section-brooks-ghost-amp-review-running-performance"><span>Brooks Ghost Amp review: Running performance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="L77zCArEw2RQhr3s8533bg" name="Brooks Ghost Amp-8" alt="Brooks Ghost Amp" src="https://cdn.mos.cms.futurecdn.net/L77zCArEw2RQhr3s8533bg-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I used the Ghost Amp as part of my <a href="https://www.tomsguide.com/wellness/running/im-a-marathoner-and-this-is-how-and-why-i-use-a-running-shoe-rotation-in-my-training">running shoe rotation</a> for a couple of weeks of marathon training, mainly doing easy, steady daily sessions in the shoe, along with some strides.</p><p>I’ve been testing Ghost and Glycerin shoes for a decade, and while they are always solid, reliable options, the Ghost 18 felt a little dated when I tested it this year.</p><p>The Ghost Amp is the change the line needed, with the livelier midsole foam, lower drop, and more rockered feel bringing it up to date and giving it a more versatile ride than the Ghost 18.</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="hpyVQuyKCUqNKPH6PNZtcg" name="Brooks Ghost Amp-9" alt="Brooks Ghost Amp" src="https://cdn.mos.cms.futurecdn.net/hpyVQuyKCUqNKPH6PNZtcg-1920-80.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>While it’s not a pure speedster, I found that running at a steady or tempo pace in the Ghost Amp felt smooth and natural, and it’s also comfortable for long easy runs.</p><p>The foam isn't as soft and springy as some, though, and it would be great to see Brooks release a shoe like this with a full PEBA midsole rather than the EVA/PEBA blend used here. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ok3L8sHmXdzECMrK6rL7Xg" name="Brooks Ghost Amp-10" alt="Brooks Ghost Amp" src="https://cdn.mos.cms.futurecdn.net/ok3L8sHmXdzECMrK6rL7Xg-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>It brings something fresh to the Brooks lineup, but the ride isn’t as fun or versatile as some rivals from other brands. The forefoot is also a tad thin on the Ghost Amp, so it isn't as comfortable in that area over long distances as a shoe like the Novablast 6, for example.</p><p>That said, one advantage of the slightly firmer material and lower profile is that the Ghost Amp feels naturally stable and is more supportive than some lightweight daily trainers in this area, like the <a href="https://www.tomsguide.com/wellness/running/its-been-over-a-year-since-i-reviewed-the-adidas-adizero-evo-sl-heres-5-reasons-why-its-still-my-go-to-running-shoe">Adidas Adizero Evo SL</a>.</p><h2 class="article-body__section" id="section-should-you-buy-the-brooks-ghost-amp"><span>Should you buy the Brooks Ghost Amp?</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="robSi6bEv43DM5N3YGiDbg" name="Brooks Ghost Amp-11" alt="Brooks Ghost Amp" src="https://cdn.mos.cms.futurecdn.net/robSi6bEv43DM5N3YGiDbg-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Brooks Ghost Amp is a good daily trainer and would be my pick from the brand’s lineup, unless you want the most cushioned ride possible, in which case the <a href="https://www.tomsguide.com/wellness/running/brooks-glycerin-max-2-review">Brooks Glycerin Max 2</a> is worth the upgrade.</p><p>Outside of Brooks, however, there are several shoes I’d go for first, starting with the Asics Novablast 6, which is more comfortable and just as light and versatile as the Brooks, or the Puma Deviate Pure Nitro, another great all-rounder.</p><p>The Adidas Evo SL or <a href="https://www.tomsguide.com/wellness/running/i-bought-this-cheap-chinese-running-shoe-to-see-how-it-compares-to-the-biggest-brands-and-it-blew-me-away">Dynafish Xiaonian</a> are also good options for those seeking a daily trainer that can handle fast runs well in particular.</p><p>I always prefer the <a href="https://www.tomsguide.com/wellness/running/hoka-clifton-pro-review">Hoka Clifton Pro</a>, which is a bit softer and more cushioned than the Ghost Amp, with a similar rockered ride and good stability, though a bit pricier.</p><p>It’s great to see Brooks move the Ghost in this direction, though, and I’m excited to see what happens with the future of the Amp, but right now it’s not topping my to-buy list for daily trainers.</p><div data-widget-type="multimodelreview" data-model-name="Brooks Ghost Amp"></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/running/i-ran-40-miles-in-the-brooks-ghost-amp-and-id-actually-buy-it-over-the-ghost-18</link>
                                                                            <description>
                            <![CDATA[ The Brooks Ghost Amp is a more energetic daily trainer than the Ghost 18 and a welcome addition to Brooks’ line-up, but it faces stiff competition from other brands. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">2qbsdaiAYXCo8aQ6BVKbBX</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/DgsvuRDTr5A2WkK2ghMUYg-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 17 Oct 2026 09:30:00 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Running]]></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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/DgsvuRDTr5A2WkK2ghMUYg-1920-80.jpg">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Brooks Ghost Amp]]></media:description>                                                            <media:text><![CDATA[Brooks Ghost Amp]]></media:text>
                                <media:title type="plain"><![CDATA[Brooks Ghost Amp]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/DgsvuRDTr5A2WkK2ghMUYg-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>The Brooks line-up now has more ghosts than an episode of Scooby-Doo, but if I were only going to keep one of the Ghost 18, Ghost Max 4 and Ghost Amp, it would definitely be the Amp.</p><p>It’s exactly the type of shoe Brooks needed to modernize the Ghost and its array of daily trainers, with the Ghost Amp livelier and more versatile than the various Ghosts and Glycerins you can buy.</p><p>I enjoyed using the shoe for daily runs at easy, steady paces, with the new DNA Hype midsole foam and improved forefoot rocker making the Ghost Amp feel smooth and energetic.</p><p>However, in its category, the Brooks Ghost Amp competes with some of the best running shoes available, and there are options I’d buy ahead of it, like the bouncier <a href="https://www.tomsguide.com/wellness/running/asics-novablast-6-review">Asics Novablast 6 </a>or the lighter <a href="https://www.tomsguide.com/wellness/running/puma-deviate-pure-nitro-review">Puma Deviate Pure Nitro</a>.</p><h2 class="article-body__section" id="section-brooks-ghost-amp-review-price-and-availability"><span>Brooks Ghost Amp review: Price and availability</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="CYemZ3bqXSyShoHrVuqoYg" name="Brooks Ghost Amp-3" alt="Brooks Ghost Amp" src="https://cdn.mos.cms.futurecdn.net/CYemZ3bqXSyShoHrVuqoYg-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Brooks Ghost Amp launched in July 2026 and costs $150 in the U.S. and £135 in the U.K., which is the same price as the <a href="https://www.tomsguide.com/wellness/running/brooks-ghost-18-review">Brooks Ghost 18</a>.</p><p>It’s a good value shoe that comes in at around the same price as many of the most popular daily trainers, including the Asics Novablast 6, <a href="https://www.tomsguide.com/wellness/running/nike-pegasus-42-review">Nike Pegasus 42</a> and <a href="https://www.tomsguide.com/wellness/running/hoka-clifton-11-review">Hoka Clifton 11</a>.</p><h2 class="article-body__section" id="section-brooks-ghost-amp-review-design-and-fit"><span>Brooks Ghost Amp review: Design and fit</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ieHfoCkEEUUph8y8ACR9eg" name="Brooks Ghost Amp-4" alt="Brooks Ghost Amp" src="https://cdn.mos.cms.futurecdn.net/ieHfoCkEEUUph8y8ACR9eg-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Ghost Amp is currently available in seven colors, including the light blue design I tested. There's a wide version as well as the standard, and I found it fit me well in my normal running shoe size.</p><p>One big difference between it and the Ghost 18 is that the Ghost Amp has a 6mm drop from heel to toe, instead of the Ghost’s traditional 10mm.</p><p>The stack height is 36mm at the heel and 30mm at the forefoot, so the Ghost Amp isn't as maxed out as many daily trainers these days, which have 40mm of foam or more at the heel.</p><p>It weighs 9.3oz in my US men’s size 10, which is 1.4oz lighter than the Ghost 18 in my size. It’s not a featherweight, but for a daily trainer with a padded upper and thick outsole, the Ghost Amp is impressively light.</p><h3 class="article-body__section" id="section-upper"><span>Upper</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="zyVWAr7HGfFaMHHw7A2cdg" name="Brooks Ghost Amp-5" alt="Brooks Ghost Amp" src="https://cdn.mos.cms.futurecdn.net/zyVWAr7HGfFaMHHw7A2cdg-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Ghost Amp’s upper is quite a thick knit material with plenty of padding around the collar and tongue. It has a stiff internal heel counter to add more support at the back of the shoe.</p><p>I prefer a more minimal upper myself, but the Ghost Amp was comfortable and held my foot securely during runs, and it retains the plush step-in feel expected of the Ghost and Glycerin lines.</p><h3 class="article-body__section" id="section-midsole"><span>Midsole</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ZsG2aPUq8gq3z8VvWYYWag" name="Brooks Ghost Amp-6" alt="Brooks Ghost Amp" src="https://cdn.mos.cms.futurecdn.net/ZsG2aPUq8gq3z8VvWYYWag-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Ghost Amp uses a new midsole foam called DNA Hype, which is a <a href="https://www.tomsguide.com/wellness/running/fantastic-foams-and-supercritical-science-why-running-shoes-have-improved-so-much-in-the-past-10-years-explained-by-an-expert-who-makes-them">supercritical material</a> made from a blend of PEBA and EVA foams. </p><p>It’s not as springy as the DNA Gold foam used in some Brooks shoes, which is made entirely of PEBA, but it’s livelier than the EVA midsole on the Ghost 18.</p><p>The Ghost Amp also introduces Brooks’ SpringRamp tech in the forefoot, which is a section of firmer foam designed to add more propulsion to your toe-offs.</p><h3 class="article-body__section" id="section-outsole"><span>Outsole</span></h3><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="hEj4eLGj3RyByXXGSYVHZg" name="Brooks Ghost Amp-7" alt="Brooks Ghost Amp" src="https://cdn.mos.cms.futurecdn.net/hEj4eLGj3RyByXXGSYVHZg-1920-80.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>While it doesn’t have a full outsole, a thick layer of rubber covers most of the forefoot and heel on the Ghost Amp, and I have no concerns about its grip or durability after testing.</p><p>It’s not quite as thick and extensive an outsole as the Ghost 18, but the trade-off is worth it to have the lighter shoe, as there’s still plenty of rubber on the bottom of the Amp.</p><h2 class="article-body__section" id="section-brooks-ghost-amp-review-running-performance"><span>Brooks Ghost Amp review: Running performance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="L77zCArEw2RQhr3s8533bg" name="Brooks Ghost Amp-8" alt="Brooks Ghost Amp" src="https://cdn.mos.cms.futurecdn.net/L77zCArEw2RQhr3s8533bg-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>I used the Ghost Amp as part of my <a href="https://www.tomsguide.com/wellness/running/im-a-marathoner-and-this-is-how-and-why-i-use-a-running-shoe-rotation-in-my-training">running shoe rotation</a> for a couple of weeks of marathon training, mainly doing easy, steady daily sessions in the shoe, along with some strides.</p><p>I’ve been testing Ghost and Glycerin shoes for a decade, and while they are always solid, reliable options, the Ghost 18 felt a little dated when I tested it this year.</p><p>The Ghost Amp is the change the line needed, with the livelier midsole foam, lower drop, and more rockered feel bringing it up to date and giving it a more versatile ride than the Ghost 18.</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="hpyVQuyKCUqNKPH6PNZtcg" name="Brooks Ghost Amp-9" alt="Brooks Ghost Amp" src="https://cdn.mos.cms.futurecdn.net/hpyVQuyKCUqNKPH6PNZtcg-1920-80.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>While it’s not a pure speedster, I found that running at a steady or tempo pace in the Ghost Amp felt smooth and natural, and it’s also comfortable for long easy runs.</p><p>The foam isn't as soft and springy as some, though, and it would be great to see Brooks release a shoe like this with a full PEBA midsole rather than the EVA/PEBA blend used here. </p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="ok3L8sHmXdzECMrK6rL7Xg" name="Brooks Ghost Amp-10" alt="Brooks Ghost Amp" src="https://cdn.mos.cms.futurecdn.net/ok3L8sHmXdzECMrK6rL7Xg-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>It brings something fresh to the Brooks lineup, but the ride isn’t as fun or versatile as some rivals from other brands. The forefoot is also a tad thin on the Ghost Amp, so it isn't as comfortable in that area over long distances as a shoe like the Novablast 6, for example.</p><p>That said, one advantage of the slightly firmer material and lower profile is that the Ghost Amp feels naturally stable and is more supportive than some lightweight daily trainers in this area, like the <a href="https://www.tomsguide.com/wellness/running/its-been-over-a-year-since-i-reviewed-the-adidas-adizero-evo-sl-heres-5-reasons-why-its-still-my-go-to-running-shoe">Adidas Adizero Evo SL</a>.</p><h2 class="article-body__section" id="section-should-you-buy-the-brooks-ghost-amp"><span>Should you buy the Brooks Ghost Amp?</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="robSi6bEv43DM5N3YGiDbg" name="Brooks Ghost Amp-11" alt="Brooks Ghost Amp" src="https://cdn.mos.cms.futurecdn.net/robSi6bEv43DM5N3YGiDbg-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="1125" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The Brooks Ghost Amp is a good daily trainer and would be my pick from the brand’s lineup, unless you want the most cushioned ride possible, in which case the <a href="https://www.tomsguide.com/wellness/running/brooks-glycerin-max-2-review">Brooks Glycerin Max 2</a> is worth the upgrade.</p><p>Outside of Brooks, however, there are several shoes I’d go for first, starting with the Asics Novablast 6, which is more comfortable and just as light and versatile as the Brooks, or the Puma Deviate Pure Nitro, another great all-rounder.</p><p>The Adidas Evo SL or <a href="https://www.tomsguide.com/wellness/running/i-bought-this-cheap-chinese-running-shoe-to-see-how-it-compares-to-the-biggest-brands-and-it-blew-me-away">Dynafish Xiaonian</a> are also good options for those seeking a daily trainer that can handle fast runs well in particular.</p><p>I always prefer the <a href="https://www.tomsguide.com/wellness/running/hoka-clifton-pro-review">Hoka Clifton Pro</a>, which is a bit softer and more cushioned than the Ghost Amp, with a similar rockered ride and good stability, though a bit pricier.</p><p>It’s great to see Brooks move the Ghost in this direction, though, and I’m excited to see what happens with the future of the Amp, but right now it’s not topping my to-buy list for daily trainers.</p><div data-widget-type="multimodelreview" data-model-name="Brooks Ghost Amp"></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I did 50 Cossack squats a day for a week — here’s what happened to my hip mobility and lower back ]]></title>
                                                                                                <dc:content><![CDATA[ <p>When it comes to building a strong lower body, the first moves that come to mind are probably squats and lunges, but you might be missing a trick. The Cossack squat is the powerhouse move you’re probably not doing, and it will help unlock your hips and ankles. Read on to find out more. </p><p>As a reminder, if you’re a complete beginner, pregnant or postpartum, or you’re returning to exercise following an injury or surgery, it’s always best to seek personalized advice from a qualified professional. </p><h3 class="article-body__section" id="section-how-to-do-a-cossack-squat"><span>How to do a Cossack squat </span></h3><p>Let’s start with how to do a Cossack squat with good form. It’s a good idea to master the bodyweight version before adding weight. </p><iframe src="https://content.jwplatform.com/players/DssxDttZ.html" id="DssxDttZ" title="Project Move - Cossack Squat" width="960" height="540" frameborder="0" scrolling="auto" allowfullscreen=""></iframe><ul><li>Start by getting into a wide stance, with your feet roughly twice shoulder-width apart. Point both toes forward, or slightly turned out and hold your hands together at chest height.</li><li>Shift your weight to one side, bend your knee and sit your hips back into a side squat, keeping your chest elevated.</li><li>As you lower, allow the non-working leg to remain straight, but pivot on its heel so the toes point straight up toward the ceiling.</li><li>Press firmly through the floor with the working foot to push up to your starting position and repeat on the opposite side.</li></ul><p>Keep switching sides, aiming for 8-10 reps on each side. To add intensity, hold one of the <a href="https://www.tomsguide.com/wellness/fitness/best-adjustable-dumbbells">best adjustable dumbbells </a>in both hands in front of your chest. </p><h3 class="article-body__section" id="section-what-are-the-benefits"><span>What are the benefits? </span></h3><p><strong>Helps with hip and ankle mobility </strong></p><p>This deep squat requires full range of motion in the hip and ankle joints, helping improve hip and ankle mobility. It’s a great one for runners or if you spend a lot of time sitting behind a desk. </p><p>When your hip flexors and adductors are tight, your pelvis can also lack full mobility. When this happens, your lower back compensates, which can lead to pain or tension. Unlocking your hip flexors and restoring deep internal and external rotation in the hips can remove this stress from your lumbar spine. </p><p><strong>Works on the groin and adductors </strong></p><p>Unlike standard squats, with the Cossack squat, you’re loading the adductors at their longest stretch. This can significantly reduce your risk of groin strains and pulls. </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="4SqJukPfYSQw9CfHZsCte5" name="cossack" alt="Cossack squat performed on yoga mat" src="https://cdn.mos.cms.futurecdn.net/4SqJukPfYSQw9CfHZsCte5-1920-80.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><strong>You’re working on your lateral stabilizers </strong></p><p>Most typical strength training exercises, like squats and lunges, focus on the sagittal plane as you move forward and backward. Working on your side-to-side strength targets the small stabilizer muscles that are often neglected, making your lower body stronger. </p><h3 class="article-body__section" id="section-i-did-50-cossack-squats-a-day-for-a-week-here-s-what-happened-to-my-hip-mobility-and-lower-back"><span>I did 50 Cossack squats a day for a week — here’s what happened to my hip mobility and lower back</span></h3><p>So what happened when I added this simple-sounding squat into my daily routine for a week? The first thing I learned was that this move is anything but simple. It might look easy on paper, but the reality was that my hip flexors were so tight at week 19 of my 20-week marathon training block that I found it extremely difficult to sink down into a single-leg squat, let alone complete 25 reps on each side. </p><p>I definitely found my right hip a lot tighter than my left (to be expected; I’m right-handed and most people have a stronger side), highlighting how I really needed to work on loosening these tight muscles now that I’m in my taper. </p><p>I stuck to the bodyweight version of this move for a full week, and while I’m still not ready to hold a dumbbell, I have noticed my form has improved. I can’t sink awfully low into the squat, but I can feel a much deeper stretch in my adductors as I move from side to side. It will definitely stay part of my strength routine post-marathon, but I think I’ll stick to 10 reps rather than 50 a week before my next race. </p><p>What are you waiting for? Stand up from your desk and give this one a go.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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/i-teach-people-how-to-be-strong-and-mobile-this-is-the-one-exercise-i-regret-ignoring-for-years" target="_blank">I teach people how to be strong and mobile: this is the one exercise I regret ignoring for years</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> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/workouts/i-did-50-cossack-squats-a-day-for-a-week-heres-what-happened-to-my-hip-mobility-and-lower-back</link>
                                                                            <description>
                            <![CDATA[ The Cossack squat is the powerhouse move you’re probably not doing, and it will help unlock your hips and ankles. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">zQcF7zU9SwRyhgL8E9XCrD</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/DpCdkbNM4FwVLLijuyMez9-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Sat, 17 Oct 2026 05:00:00 +0000</pubDate>                                                                                                                                <updated>Sat, 17 Oct 2026 12:04:17 +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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/DpCdkbNM4FwVLLijuyMez9-1920-80.jpg">
                                                            <media:credit><![CDATA[Getty images]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Woman performing a Cossack squat with right knee bent and left knee extended with backdrop of a river ]]></media:description>                                                            <media:text><![CDATA[Woman performing a Cossack squat with right knee bent and left knee extended with backdrop of a river ]]></media:text>
                                <media:title type="plain"><![CDATA[Woman performing a Cossack squat with right knee bent and left knee extended with backdrop of a river ]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/DpCdkbNM4FwVLLijuyMez9-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>When it comes to building a strong lower body, the first moves that come to mind are probably squats and lunges, but you might be missing a trick. The Cossack squat is the powerhouse move you’re probably not doing, and it will help unlock your hips and ankles. Read on to find out more. </p><p>As a reminder, if you’re a complete beginner, pregnant or postpartum, or you’re returning to exercise following an injury or surgery, it’s always best to seek personalized advice from a qualified professional. </p><h3 class="article-body__section" id="section-how-to-do-a-cossack-squat"><span>How to do a Cossack squat </span></h3><p>Let’s start with how to do a Cossack squat with good form. It’s a good idea to master the bodyweight version before adding weight. </p><iframe src="https://content.jwplatform.com/players/DssxDttZ.html" id="DssxDttZ" title="Project Move - Cossack Squat" width="960" height="540" frameborder="0" scrolling="auto" allowfullscreen=""></iframe><ul><li>Start by getting into a wide stance, with your feet roughly twice shoulder-width apart. Point both toes forward, or slightly turned out and hold your hands together at chest height.</li><li>Shift your weight to one side, bend your knee and sit your hips back into a side squat, keeping your chest elevated.</li><li>As you lower, allow the non-working leg to remain straight, but pivot on its heel so the toes point straight up toward the ceiling.</li><li>Press firmly through the floor with the working foot to push up to your starting position and repeat on the opposite side.</li></ul><p>Keep switching sides, aiming for 8-10 reps on each side. To add intensity, hold one of the <a href="https://www.tomsguide.com/wellness/fitness/best-adjustable-dumbbells">best adjustable dumbbells </a>in both hands in front of your chest. </p><h3 class="article-body__section" id="section-what-are-the-benefits"><span>What are the benefits? </span></h3><p><strong>Helps with hip and ankle mobility </strong></p><p>This deep squat requires full range of motion in the hip and ankle joints, helping improve hip and ankle mobility. It’s a great one for runners or if you spend a lot of time sitting behind a desk. </p><p>When your hip flexors and adductors are tight, your pelvis can also lack full mobility. When this happens, your lower back compensates, which can lead to pain or tension. Unlocking your hip flexors and restoring deep internal and external rotation in the hips can remove this stress from your lumbar spine. </p><p><strong>Works on the groin and adductors </strong></p><p>Unlike standard squats, with the Cossack squat, you’re loading the adductors at their longest stretch. This can significantly reduce your risk of groin strains and pulls. </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="4SqJukPfYSQw9CfHZsCte5" name="cossack" alt="Cossack squat performed on yoga mat" src="https://cdn.mos.cms.futurecdn.net/4SqJukPfYSQw9CfHZsCte5-1920-80.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><strong>You’re working on your lateral stabilizers </strong></p><p>Most typical strength training exercises, like squats and lunges, focus on the sagittal plane as you move forward and backward. Working on your side-to-side strength targets the small stabilizer muscles that are often neglected, making your lower body stronger. </p><h3 class="article-body__section" id="section-i-did-50-cossack-squats-a-day-for-a-week-here-s-what-happened-to-my-hip-mobility-and-lower-back"><span>I did 50 Cossack squats a day for a week — here’s what happened to my hip mobility and lower back</span></h3><p>So what happened when I added this simple-sounding squat into my daily routine for a week? The first thing I learned was that this move is anything but simple. It might look easy on paper, but the reality was that my hip flexors were so tight at week 19 of my 20-week marathon training block that I found it extremely difficult to sink down into a single-leg squat, let alone complete 25 reps on each side. </p><p>I definitely found my right hip a lot tighter than my left (to be expected; I’m right-handed and most people have a stronger side), highlighting how I really needed to work on loosening these tight muscles now that I’m in my taper. </p><p>I stuck to the bodyweight version of this move for a full week, and while I’m still not ready to hold a dumbbell, I have noticed my form has improved. I can’t sink awfully low into the squat, but I can feel a much deeper stretch in my adductors as I move from side to side. It will definitely stay part of my strength routine post-marathon, but I think I’ll stick to 10 reps rather than 50 a week before my next race. </p><p>What are you waiting for? Stand up from your desk and give this one a go.</p><div style="min-height: 250px;">                                <div class="kwizly-quiz kwizly-eEq7ae"></div>                            </div>                            <script src="https://kwizly.com/embed/eEq7ae.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/i-teach-people-how-to-be-strong-and-mobile-this-is-the-one-exercise-i-regret-ignoring-for-years" target="_blank">I teach people how to be strong and mobile: this is the one exercise I regret ignoring for years</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[ Patagonia, Arc’teryx and The North Face are up to 50% off at REI — 27 best apparel deals for fall ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Now that temperatures are starting to drop, investing in some high-quality outerwear is a must. While it’s worth spending a little extra on pieces built to last, the good news is you don’t have to break the bank to find something great. </p><p>Case in point: <a href="https://www.rei.com/f/scd-deals" target="_blank" rel="nofollow">REI's sale section is packed to the brim with impressive deals</a> from top brands like Patagonia, The North Face, Arc'teryx and more. The outdoor retailer is offering discounts of up to 50% on lightweight jackets, fleeces, hiking gear and more. For instance, <a href="https://www.rei.com/product/143470/patagonia-houdini-jacket-mens" target="_blank" rel="nofollow">the popular Patagonia Houdini Jacket is down to just $82</a> and is the perfect layer for fall adventures.</p><p>There's plenty more deals where that came from! Below, I've rounded up my favorite REI styles. Keep scrolling to check out the deals that are actually worth shopping for fall. </p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><a href="https://www.rei.com/f/scd-deals" target="_blank" rel="nofollow"><strong>shop REI's fall sale</strong></a></li><li><strong>Camping gear: </strong><a href="https://www.rei.com/c/camping-and-hiking/f/scd-deals" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li><li><strong>Vuori: </strong><a href="https://www.rei.com/b/vuori/f/scd-deals?" target="_blank" rel="nofollow"><strong>up to 40% off</strong></a></li><li><strong>Arc'teryx: </strong><a href="https://www.rei.com/b/arcteryx/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;sort=min-price&amp;r=f%3Bb" target="_blank" rel="nofollow"><strong>apparel from $24</strong></a></li><li><strong>Columbia: </strong><a href="https://www.rei.com/b/columbia/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;sort=min-price&amp;irclickid=3KjxOUTuLxyKWYwT3BUaGy3DUkp2c0Uto0pyw40" target="_blank" rel="nofollow"><strong>apparel from $14</strong></a></li><li><strong>Patagonia: </strong><a href="https://www.rei.com/b/patagonia/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;r=f%3Bb&amp;sort=min-price" target="_blank" rel="nofollow"><strong>apparel/accessories from $15</strong></a></li><li><strong>Marmot: </strong><a href="https://www.rei.com/b/marmot/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;sort=min-price&amp;r=f%3Bb" target="_blank" rel="nofollow"><strong>apparel from $15</strong></a></li><li><strong>The North Face: </strong><a href="https://www.rei.com/b/the-north-face/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;r=f%3Bb&amp;sort=min-price" target="_blank" rel="nofollow"><strong>apparel from $16</strong></a></li><li><strong>Yeti: </strong><a href="https://www.rei.com/b/yeti/f/scd-deals?" target="_blank" rel="nofollow"><strong>water bottles from $17</strong></a></li><li><strong>Adidas: </strong><a href="https://www.rei.com/b/adidas/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;r=f%3Bb&amp;sort=min-price" target="_blank" rel="nofollow"><strong>sports bras/shirts from $19</strong></a></li><li><strong>Saucony: </strong><a href="https://www.rei.com/b/saucony/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;sort=min-price&amp;r=f%3Bb" target="_blank" rel="nofollow"><strong>running gear from $46</strong></a><strong></strong></li></ul><h3 class="article-body__section" id="section-top-rei-deals"><span>Top REI Deals</span></h3><div class="product"><a data-dimension112="ab7c8b68-c96d-11f1-ba62-9fc21c58633d" data-action="Deal Block" data-label="Houdini Jacket (Men's)" data-dimension48="Houdini Jacket (Men's)" data-dimension25="$82" href="https://www.rei.com/product/143470/patagonia-houdini-jacket-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:588px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="8GQeT4DV45yR8hUW8QhMEC" name="REI Patagonia jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/8GQeT4DV45yR8hUW8QhMEC-1920-80.jpg" mos="" align="middle" fullscreen="" width="588" height="588" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/143470/patagonia-houdini-jacket-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8b68-c96d-11f1-ba62-9fc21c58633d" data-action="Deal Block" data-label="Houdini Jacket (Men's)" data-dimension48="Houdini Jacket (Men's)" data-dimension25="$82">Houdini Jacket (Men's): was $109 now $82</a></strong><br />Lightweight and compact enough to stuff into a back pocket yet warm and weather-resistant enough to keep you dry and comfy in moderate rain and chilliness, the Patagonia Houdini really lives up to its magical name.  <a class="view-deal button" href="https://www.rei.com/product/143470/patagonia-houdini-jacket-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8b68-c96d-11f1-ba62-9fc21c58633d" data-action="Deal Block" data-label="Houdini Jacket (Men's)" data-dimension48="Houdini Jacket (Men's)" data-dimension25="$82">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c8bd6-c96d-11f1-8d0b-9f4b4962e70c" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$139" href="https://www.rei.com/product/C01854/the-north-face-aconcagua-3-down-jacket-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="3NRirLjHRfkq2GuUVcaUTa" name="The North Face Jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3NRirLjHRfkq2GuUVcaUTa-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01854/the-north-face-aconcagua-3-down-jacket-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8bd6-c96d-11f1-8d0b-9f4b4962e70c" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$139">Aconcagua 3 Jacket (Men's): was $200 now $139</a></strong><br />This lightweight puffer blends recycled down with synthetic insulation for maximum warmth and weather resistance in a tidy, easy-to-stow package. Zonal sheet insulation and a water-repellant finish round out the feature set.<a class="view-deal button" href="https://www.rei.com/product/C01854/the-north-face-aconcagua-3-down-jacket-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8bd6-c96d-11f1-8d0b-9f4b4962e70c" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$139">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c8c44-c96d-11f1-aa6b-d9293a4bf4b6" data-action="Deal Block" data-label="Beta SL Jacket (Men's)" data-dimension48="Beta SL Jacket (Men's)" data-dimension25="$299" href="https://www.rei.com/product/235112/arcteryx-beta-sl-jacket-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="qb97kzq9mCRC8aoRkEXVCX" name="Arc'teryx Beta" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/qb97kzq9mCRC8aoRkEXVCX-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/235112/arcteryx-beta-sl-jacket-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8c44-c96d-11f1-aa6b-d9293a4bf4b6" data-action="Deal Block" data-label="Beta SL Jacket (Men's)" data-dimension48="Beta SL Jacket (Men's)" data-dimension25="$299">Beta SL Jacket (Men's): was $500 now $299</a></strong><br />Lightweight, comfortable and breathable, this durable waterproof and windproof jacket will protect you from the elements without sacrificing features or packability. It's a great option for layering or wearing on its own. <a class="view-deal button" href="https://www.rei.com/product/235112/arcteryx-beta-sl-jacket-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8c44-c96d-11f1-aa6b-d9293a4bf4b6" data-action="Deal Block" data-label="Beta SL Jacket (Men's)" data-dimension48="Beta SL Jacket (Men's)" data-dimension25="$299">View Deal</a></p></div><h3 class="article-body__section" id="section-patagonia"><span>Patagonia</span></h3><div class="product"><a data-dimension112="ab7c8d20-c96d-11f1-a6c9-6fc1636449ae" data-action="Deal Block" data-label="Baggies Shorts (Men’s)" data-dimension48="Baggies Shorts (Men’s)" data-dimension25="$54" href="https://www.rei.com/product/242831/patagonia-baggies-5-shorts-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1504px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="JtXgyevXrT5SUBGhvhBYQF" name="patagonia baggies" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/JtXgyevXrT5SUBGhvhBYQF-1920-80.jpg" mos="" align="middle" fullscreen="" width="1504" height="1504" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/242831/patagonia-baggies-5-shorts-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8d20-c96d-11f1-a6c9-6fc1636449ae" data-action="Deal Block" data-label="Baggies Shorts (Men’s)" data-dimension48="Baggies Shorts (Men’s)" data-dimension25="$54">Baggies Shorts (Men’s): was $69 now $54</a></strong><br />Summer may be officially over, but Patagonia's Baggie shorts are suitable for both inside and out of the water. And as the brand are clearing out their end-of-season styles, you can get these shorts for as low as $54.<a class="view-deal button" href="https://www.rei.com/product/242831/patagonia-baggies-5-shorts-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8d20-c96d-11f1-a6c9-6fc1636449ae" data-action="Deal Block" data-label="Baggies Shorts (Men’s)" data-dimension48="Baggies Shorts (Men’s)" data-dimension25="$54">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c8d8e-c96d-11f1-b5b4-03a9de12bf9f" data-action="Deal Block" data-label="Outdoor Everyday Pants (Women's)" data-dimension48="Outdoor Everyday Pants (Women's)" data-dimension25="$68" href="https://www.rei.com/product/228412/patagonia-outdoor-everyday-pants-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="zoeCcCwPahdqAedoN2ztbX" name="pants" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zoeCcCwPahdqAedoN2ztbX-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/228412/patagonia-outdoor-everyday-pants-womens" target="_blank" rel="nofollow" data-dimension112="ab7c8d8e-c96d-11f1-b5b4-03a9de12bf9f" data-action="Deal Block" data-label="Outdoor Everyday Pants (Women's)" data-dimension48="Outdoor Everyday Pants (Women's)" data-dimension25="$68">Outdoor Everyday Pants (Women's): was $99 now $68</a></strong><br />Although they look like sweatpants, the Patagonia Outdoor Everyday Pants are ideal for hikes and outdoor activities. As they're wide-legged, they're super comfortable, and are even water-repellant. They're on sale in three different colors.<a class="view-deal button" href="https://www.rei.com/product/228412/patagonia-outdoor-everyday-pants-womens" target="_blank" rel="nofollow" data-dimension112="ab7c8d8e-c96d-11f1-b5b4-03a9de12bf9f" data-action="Deal Block" data-label="Outdoor Everyday Pants (Women's)" data-dimension48="Outdoor Everyday Pants (Women's)" data-dimension25="$68">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c8dfc-c96d-11f1-9fb7-6da03d377a2b" data-action="Deal Block" data-label="P-6 Logo Uprisal Hoody (Unisex)" data-dimension48="P-6 Logo Uprisal Hoody (Unisex)" data-dimension25="$71" href="https://www.rei.com/product/191626/patagonia-p-6-logo-uprisal-hoody" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1707px;"><p class="vanilla-image-block" style="padding-top:117.16%;"><img id="AxhSkgAYP5VCo4UWcfgBNi" name="Patagonia hoodie" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/AxhSkgAYP5VCo4UWcfgBNi-1920-80.jpg" mos="" align="middle" fullscreen="" width="1707" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/191626/patagonia-p-6-logo-uprisal-hoody" target="_blank" rel="nofollow" data-dimension112="ab7c8dfc-c96d-11f1-9fb7-6da03d377a2b" data-action="Deal Block" data-label="P-6 Logo Uprisal Hoody (Unisex)" data-dimension48="P-6 Logo Uprisal Hoody (Unisex)" data-dimension25="$71">P-6 Logo Uprisal Hoody (Unisex): was $95 now $71</a></strong><br />This is such a classic versatile hoody, I can't quite believe it's discounted in three colors. This is the kind of sweater that never goes out of style. This hoody is made from 30 plastic bottles, so you know you're wearing something that is benefitting the planet.  <a class="view-deal button" href="https://www.rei.com/product/191626/patagonia-p-6-logo-uprisal-hoody" target="_blank" rel="nofollow" data-dimension112="ab7c8dfc-c96d-11f1-9fb7-6da03d377a2b" data-action="Deal Block" data-label="P-6 Logo Uprisal Hoody (Unisex)" data-dimension48="P-6 Logo Uprisal Hoody (Unisex)" data-dimension25="$71">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c8e6a-c96d-11f1-93be-959557990a53" data-action="Deal Block" data-label="Ahnya Pullover (Women's)" data-dimension48="Ahnya Pullover (Women's)" data-dimension25="$93" href="https://www.rei.com/product/250042/patagonia-ahnya-full-zip-hoody-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1600px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="8Ja4UguKzZauzQ2r3qNtGm" name="patagonia" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/8Ja4UguKzZauzQ2r3qNtGm-1920-80.jpg" mos="" align="middle" fullscreen="" width="1600" height="1600" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/250042/patagonia-ahnya-full-zip-hoody-womens" target="_blank" rel="nofollow" data-dimension112="ab7c8e6a-c96d-11f1-93be-959557990a53" data-action="Deal Block" data-label="Ahnya Pullover (Women's)" data-dimension48="Ahnya Pullover (Women's)" data-dimension25="$93">Ahnya Pullover (Women's): was $135 now $93</a></strong><br />Nothing says fall apparel like a lightweight pullover. The sweatshirt is made with Regenerative Organic Certified cotton and recycled polyester fleece and spandex, with front pockets and rib-knit cuffs. It's perfect for throwing over a tee or wearing under a jacket.<a class="view-deal button" href="https://www.rei.com/product/250042/patagonia-ahnya-full-zip-hoody-womens" target="_blank" rel="nofollow" data-dimension112="ab7c8e6a-c96d-11f1-93be-959557990a53" data-action="Deal Block" data-label="Ahnya Pullover (Women's)" data-dimension48="Ahnya Pullover (Women's)" data-dimension25="$93">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c8ece-c96d-11f1-b064-adc37fb2618e" data-action="Deal Block" data-label="Houdini Half-zip" data-dimension48="Houdini Half-zip" data-dimension25="$100" href="https://www.rei.com/product/228564/patagonia-houdini-stash-half-zip-jacket-mens?color=CASCADE%2520GREEN" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1090px;"><p class="vanilla-image-block" style="padding-top:112.75%;"><img id="Ae9C3N28VXVi824kshL69a" name="Screenshot 2026-06-15 at 9.10.35 PM" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Ae9C3N28VXVi824kshL69a-1920-80.png" mos="" align="middle" fullscreen="" width="1090" height="1229" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Patagonia Houdini Half-Zip is nothing short of pure magic. This back-pocket-packable pull-over weighs about as much as a deck of playing cards, yet offers seriously solid protection from the rain, wind and chill.<a class="view-deal button" href="https://www.rei.com/product/228564/patagonia-houdini-stash-half-zip-jacket-mens?color=CASCADE%2520GREEN" target="_blank" rel="nofollow" data-dimension112="ab7c8ece-c96d-11f1-b064-adc37fb2618e" data-action="Deal Block" data-label="Houdini Half-zip" data-dimension48="Houdini Half-zip" data-dimension25="$100">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c8f3c-c96d-11f1-a1d1-b9b071c8c123" data-action="Deal Block" data-label="R1 Pullover - Women's" data-dimension48="R1 Pullover - Women's" data-dimension25="$107" href="https://www.rei.com/product/242323/patagonia-r1-pullover-womens" 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="bre5ZuSFLvwfm5qxrkvwTm" name="patagonia r1 pullover" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bre5ZuSFLvwfm5qxrkvwTm-1920-80.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/242323/patagonia-r1-pullover-womens" target="_blank" rel="nofollow" data-dimension112="ab7c8f3c-c96d-11f1-a1d1-b9b071c8c123" data-action="Deal Block" data-label="R1 Pullover - Women's" data-dimension48="R1 Pullover - Women's" data-dimension25="$107">R1 Pullover - Women's: was $155 now $107</a></strong><br />The Patagonia R1 Pullover is a midlayer, meaning it's intended to be worn between a thermal base layer and an outer waterproof or windproof jacket like the Patagonia Houdini. Right now, it's <a class="view-deal button" href="https://www.rei.com/product/242323/patagonia-r1-pullover-womens" target="_blank" rel="nofollow" data-dimension112="ab7c8f3c-c96d-11f1-a1d1-b9b071c8c123" data-action="Deal Block" data-label="R1 Pullover - Women's" data-dimension48="R1 Pullover - Women's" data-dimension25="$107">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c8faa-c96d-11f1-9c9f-0d6a1312332c" data-action="Deal Block" data-label="Daily Snap-T Pullover (Men's)" data-dimension48="Daily Snap-T Pullover (Men's)" data-dimension25="$124" href="https://www.rei.com/product/C01345/patagonia-daily-snap-t-pullover-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1560px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="WGXNCXSCXiBba8uzoeFYnS" name="Patagonia Snap T" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/WGXNCXSCXiBba8uzoeFYnS-1920-80.jpg" mos="" align="middle" fullscreen="" width="1560" height="1560" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01345/patagonia-daily-snap-t-pullover-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8faa-c96d-11f1-9c9f-0d6a1312332c" data-action="Deal Block" data-label="Daily Snap-T Pullover (Men's)" data-dimension48="Daily Snap-T Pullover (Men's)" data-dimension25="$124">Daily Snap-T Pullover (Men's): was $179 now $124</a></strong><br />This fleece is perfect to wear at the campsite during chilly evenings, or on early morning trails. The Daily Snap-T Pullover is made from 100% regenerative organic cotton as well. It's available in every single size, so you'll be able to find your perfect fit. <a class="view-deal button" href="https://www.rei.com/product/C01345/patagonia-daily-snap-t-pullover-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8faa-c96d-11f1-9c9f-0d6a1312332c" data-action="Deal Block" data-label="Daily Snap-T Pullover (Men's)" data-dimension48="Daily Snap-T Pullover (Men's)" data-dimension25="$124">View Deal</a></p></div><h3 class="article-body__section" id="section-the-north-face"><span>The North Face</span></h3><div class="product"><a data-dimension112="ab7c907c-c96d-11f1-81f0-6f15033afcf2" data-action="Deal Block" data-label="Glacier Fleece Quarter-Zip Jacket (Men's)" data-dimension48="Glacier Fleece Quarter-Zip Jacket (Men's)" data-dimension25="$45" href="https://www.rei.com/product/C11727/the-north-face-glacier-fleece-quarter-zip-jacket-mens?color=DUSK%2520BLUE" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1452px;"><p class="vanilla-image-block" style="padding-top:100.07%;"><img id="yvbgf7cVFY9masQPhTAnVU" name="TNF-02b" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/yvbgf7cVFY9masQPhTAnVU-1920-80.jpg" mos="" align="middle" fullscreen="" width="1452" height="1453" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C11727/the-north-face-glacier-fleece-quarter-zip-jacket-mens?color=DUSK%2520BLUE" target="_blank" rel="nofollow" data-dimension112="ab7c907c-c96d-11f1-81f0-6f15033afcf2" data-action="Deal Block" data-label="Glacier Fleece Quarter-Zip Jacket (Men's)" data-dimension48="Glacier Fleece Quarter-Zip Jacket (Men's)" data-dimension25="$45">Glacier Fleece Quarter-Zip Jacket (Men's): was $70 now $45</a></strong><br />The Glacier Fleece Quarter-Zip is a highly versatile garment that works both as an outer-layer and as a mid-layer, depending on temps. Plus, this deal is on the Dusk Blue variant, which I find very easy on the eyes. <a class="view-deal button" href="https://www.rei.com/product/C11727/the-north-face-glacier-fleece-quarter-zip-jacket-mens?color=DUSK%2520BLUE" target="_blank" rel="nofollow" data-dimension112="ab7c907c-c96d-11f1-81f0-6f15033afcf2" data-action="Deal Block" data-label="Glacier Fleece Quarter-Zip Jacket (Men's)" data-dimension48="Glacier Fleece Quarter-Zip Jacket (Men's)" data-dimension25="$45">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c90ea-c96d-11f1-8e86-af29db5f09ec" data-action="Deal Block" data-label="DotKnit Thermal ¼-Zip (Women's)" data-dimension48="DotKnit Thermal ¼-Zip (Women's)" data-dimension25="$64" href="https://www.rei.com/product/254013/the-north-face-dotknit-thermal-quarter-zip-pullover-womens?color=MIDNIGHT%2520PETROL" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:576px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="JkvuGYs7dyyBgbeoS9VyUF" name="The North Face dotknot" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/JkvuGYs7dyyBgbeoS9VyUF-1920-80.jpg" mos="" align="middle" fullscreen="" width="576" height="576" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/254013/the-north-face-dotknit-thermal-quarter-zip-pullover-womens?color=MIDNIGHT%2520PETROL" target="_blank" rel="nofollow" data-dimension112="ab7c90ea-c96d-11f1-8e86-af29db5f09ec" data-action="Deal Block" data-label="DotKnit Thermal ¼-Zip (Women's)" data-dimension48="DotKnit Thermal ¼-Zip (Women's)" data-dimension25="$64">DotKnit Thermal ¼-Zip (Women's): was $90 now $64</a></strong><br />If you're a runner, you need this ¼-zip for the colder months. Not only does it help regulate body temperature with its innovative insulating fabric, it also actively moves moisture away from the body.<a class="view-deal button" href="https://www.rei.com/product/254013/the-north-face-dotknit-thermal-quarter-zip-pullover-womens?color=MIDNIGHT%2520PETROL" target="_blank" rel="nofollow" data-dimension112="ab7c90ea-c96d-11f1-8e86-af29db5f09ec" data-action="Deal Block" data-label="DotKnit Thermal ¼-Zip (Women's)" data-dimension48="DotKnit Thermal ¼-Zip (Women's)" data-dimension25="$64">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c9158-c96d-11f1-b77b-ef519819e59b" data-action="Deal Block" data-label="Osito Lux Jacket (Women's)" data-dimension48="Osito Lux Jacket (Women's)" data-dimension25="$65" href="https://www.rei.com/product/250475/the-north-face-osito-lux-jacket-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1290px;"><p class="vanilla-image-block" style="padding-top:116.28%;"><img id="MZdvPZM2QPb9UsJtviZ5GJ" name="Osito Lux Jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/MZdvPZM2QPb9UsJtviZ5GJ-1920-80.jpg" mos="" align="middle" fullscreen="" width="1290" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/250475/the-north-face-osito-lux-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c9158-c96d-11f1-b77b-ef519819e59b" data-action="Deal Block" data-label="Osito Lux Jacket (Women's)" data-dimension48="Osito Lux Jacket (Women's)" data-dimension25="$65">Osito Lux Jacket (Women's): was $130 now $65</a></strong><br />The super soft Osito Jacket is made with a supersoft high-pile fleece and provides instant, lightweight warmth. It has a rib-knit collar, hem and cuffs for better warmth retention in chilly weather.<a class="view-deal button" href="https://www.rei.com/product/250475/the-north-face-osito-lux-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c9158-c96d-11f1-b77b-ef519819e59b" data-action="Deal Block" data-label="Osito Lux Jacket (Women's)" data-dimension48="Osito Lux Jacket (Women's)" data-dimension25="$65">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c91c6-c96d-11f1-8a12-073a01b255d7" data-action="Deal Block" data-label="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension48="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension25="$74" href="https://www.rei.com/product/C00697/the-north-face-yumiori-off-peak-full-zip-jacket-womens" 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="vamU4Ky2CB4QQda8nfrvm4" name="the north face yumiori jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vamU4Ky2CB4QQda8nfrvm4-1920-80.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C00697/the-north-face-yumiori-off-peak-full-zip-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c91c6-c96d-11f1-8a12-073a01b255d7" data-action="Deal Block" data-label="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension48="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension25="$74">Yumiori Off Peak Full-Zip Jacket - Women's: was $150 now $74</a></strong><br />The North Face's Yumiori fleece is a perfect hiking-slash-everyday fleece. Smartphones fit snugly into the chest pocket, one zipper even doubles as a hair tie, and it's finished with durable water repellent. Three colors are available at 51% off in sizes S-XL.<a class="view-deal button" href="https://www.rei.com/product/C00697/the-north-face-yumiori-off-peak-full-zip-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c91c6-c96d-11f1-8a12-073a01b255d7" data-action="Deal Block" data-label="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension48="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension25="$74">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c922a-c96d-11f1-b840-136b8c58f73c" data-action="Deal Block" data-label="Kikash Wind Jacket (Women's)" data-dimension48="Kikash Wind Jacket (Women's)" data-dimension25="$75" href="https://www.rei.com/product/254048/the-north-face-kikash-wind-jacket-womens" 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="euVM6xCmm2F8CfG6fPp57T" name="Kikash jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/euVM6xCmm2F8CfG6fPp57T-1920-80.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/254048/the-north-face-kikash-wind-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c922a-c96d-11f1-b840-136b8c58f73c" data-action="Deal Block" data-label="Kikash Wind Jacket (Women's)" data-dimension48="Kikash Wind Jacket (Women's)" data-dimension25="$75">Kikash Wind Jacket (Women's): was $150 now $75</a></strong><br />The Kikash Wind Jacket is built for those days when the wind won't quit. The durable nylon fabric shrugs off mountain gusts while keeping you mobile, and reflective details add crucial visibility for early starts or late finishes. The secure zip pockets and snug elastic hem make it a reliable companion for unpredictable conditions.<a class="view-deal button" href="https://www.rei.com/product/254048/the-north-face-kikash-wind-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c922a-c96d-11f1-b840-136b8c58f73c" data-action="Deal Block" data-label="Kikash Wind Jacket (Women's)" data-dimension48="Kikash Wind Jacket (Women's)" data-dimension25="$75">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c9298-c96d-11f1-a652-1be06bb24e0a" data-action="Deal Block" data-label="Alta Vista Rain Jacket (Women's)" data-dimension48="Alta Vista Rain Jacket (Women's)" data-dimension25="$79" href="https://www.rei.com/product/242819/the-north-face-alta-vista-rain-jacket-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1772px;"><p class="vanilla-image-block" style="padding-top:112.87%;"><img id="dkBbNBgcHs4GBuZg9YpfQk" name="image" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/dkBbNBgcHs4GBuZg9YpfQk-1920-80.png" mos="" align="middle" fullscreen="" width="1772" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/242819/the-north-face-alta-vista-rain-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c9298-c96d-11f1-a652-1be06bb24e0a" data-action="Deal Block" data-label="Alta Vista Rain Jacket (Women's)" data-dimension48="Alta Vista Rain Jacket (Women's)" data-dimension25="$79">Alta Vista Rain Jacket (Women's): was $160 now $79</a></strong><br />The North Face Alta Vista Rain Jacket is the kind of shell you’ll thank yourself for when the rain hits mid-hike or dog walk. It’s breathable, practical, and full of easy-access pockets. It looks great outdoors and just as good around town. I never travel without a waterproof jacket for fall city breaks, and this one fits the bill perfectly.<a class="view-deal button" href="https://www.rei.com/product/242819/the-north-face-alta-vista-rain-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c9298-c96d-11f1-a652-1be06bb24e0a" data-action="Deal Block" data-label="Alta Vista Rain Jacket (Women's)" data-dimension48="Alta Vista Rain Jacket (Women's)" data-dimension25="$79">View Deal</a></p></div><h3 class="article-body__section" id="section-arc-teryx"><span>Arc'teryx</span></h3><div class="product"><a data-dimension112="ab7c936a-c96d-11f1-8d8c-33f7642b9c57" data-action="Deal Block" data-label="Norvan Downword Logo T-Shirt (Men's)" data-dimension48="Norvan Downword Logo T-Shirt (Men's)" data-dimension25="$44" href="https://www.rei.com/product/C01313/arcteryx-norvan-downword-logo-t-shirt-mens?color=MANTIS%252FTATSU" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="PWCsPHixKKo3VfnePAiX9Z" name="Arc'teryx tee" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/PWCsPHixKKo3VfnePAiX9Z-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01313/arcteryx-norvan-downword-logo-t-shirt-mens?color=MANTIS%252FTATSU" target="_blank" rel="nofollow" data-dimension112="ab7c936a-c96d-11f1-8d8c-33f7642b9c57" data-action="Deal Block" data-label="Norvan Downword Logo T-Shirt (Men's)" data-dimension48="Norvan Downword Logo T-Shirt (Men's)" data-dimension25="$44">Norvan Downword Logo T-Shirt (Men's): was $90 now $44</a></strong><br />The<strong> </strong>Norvan Downword T-Shirt is a lightweight moisture-wicking tee designed for trail running but is an excellent tee for any outdoor adventure. It is water resistant and has an 'anti-odor' finish to keep you fresh on the trails. Take advantage of this deal now and save big!<a class="view-deal button" href="https://www.rei.com/product/C01313/arcteryx-norvan-downword-logo-t-shirt-mens?color=MANTIS%252FTATSU" target="_blank" rel="nofollow" data-dimension112="ab7c936a-c96d-11f1-8d8c-33f7642b9c57" data-action="Deal Block" data-label="Norvan Downword Logo T-Shirt (Men's)" data-dimension48="Norvan Downword Logo T-Shirt (Men's)" data-dimension25="$44">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c93d8-c96d-11f1-bc42-817072f6b981" data-action="Deal Block" data-label="Sima Hoody (Men's)" data-dimension48="Sima Hoody (Men's)" data-dimension25="$119" href="https://www.rei.com/product/C01372/arcteryx-sima-hoody-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1999px;"><p class="vanilla-image-block" style="padding-top:100.05%;"><img id="7ALJ3myuTiT2XsP4zXyHWg" name="Arc'teryx Sima" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/7ALJ3myuTiT2XsP4zXyHWg-1920-80.jpg" mos="" align="middle" fullscreen="" width="1999" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01372/arcteryx-sima-hoody-mens" target="_blank" rel="nofollow" data-dimension112="ab7c93d8-c96d-11f1-bc42-817072f6b981" data-action="Deal Block" data-label="Sima Hoody (Men's)" data-dimension48="Sima Hoody (Men's)" data-dimension25="$119">Sima Hoody (Men's): was $160 now $119</a></strong><br />This chic zip-up jacket is designed with backpackers and hikers in mind. Weighing just over six ounces, it's made from synthetic fabric with UPF 50+ sun protection. Nice and breathable, the fabric is also moisture-wicking to keep you dry.<a class="view-deal button" href="https://www.rei.com/product/C01372/arcteryx-sima-hoody-mens" target="_blank" rel="nofollow" data-dimension112="ab7c93d8-c96d-11f1-bc42-817072f6b981" data-action="Deal Block" data-label="Sima Hoody (Men's)" data-dimension48="Sima Hoody (Men's)" data-dimension25="$119">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c943c-c96d-11f1-b867-65f1e96cb788" data-action="Deal Block" data-label="Squamish Hoody - Men's" data-dimension48="Squamish Hoody - Men's" data-dimension25="$119" href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="gU2HZNV4QV8x48bVFDMoVL" name="Arc'teryx Squamish" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gU2HZNV4QV8x48bVFDMoVL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow" data-dimension112="ab7c943c-c96d-11f1-b867-65f1e96cb788" data-action="Deal Block" data-label="Squamish Hoody - Men's" data-dimension48="Squamish Hoody - Men's" data-dimension25="$119">Squamish Hoody - Men's: was $200 now $119</a></strong><br />The Arc'teryx Squamish Hoody is completely windproof and finished with DWR, making it a versatile outer layer for those nippy wintry hikes. There's even a capped hood for keeping your face dry. Currently three colors from XS-XL are discounted.<a class="view-deal button" href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow" data-dimension112="ab7c943c-c96d-11f1-b867-65f1e96cb788" data-action="Deal Block" data-label="Squamish Hoody - Men's" data-dimension48="Squamish Hoody - Men's" data-dimension25="$119">View Deal</a></p></div><h3 class="article-body__section" id="section-vuori"><span>Vuori</span></h3><div class="product"><a data-dimension112="ab7c9518-c96d-11f1-bbac-31a32c9b6065" data-action="Deal Block" data-label="Long Sleeve Strato Graphic Tee (Men's)" data-dimension48="Long Sleeve Strato Graphic Tee (Men's)" data-dimension25="$39" href="https://www.rei.com/product/173004/vuori-long-sleeve-strato-tech-t-shirt-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="Q2apw9UBKpntczusMwSp9n" name="Strato tee" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Q2apw9UBKpntczusMwSp9n-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/173004/vuori-long-sleeve-strato-tech-t-shirt-mens" target="_blank" rel="nofollow" data-dimension112="ab7c9518-c96d-11f1-bbac-31a32c9b6065" data-action="Deal Block" data-label="Long Sleeve Strato Graphic Tee (Men's)" data-dimension48="Long Sleeve Strato Graphic Tee (Men's)" data-dimension25="$39">Long Sleeve Strato Graphic Tee (Men's): was $69 now $39</a></strong><br />You can always use an extra long sleeve tee in your wardrobe — and this one will quickly become your favorite. This super soft piece of workout gear will be your go-to during your workouts, weekend adventures and lounge sessions. <a class="view-deal button" href="https://www.rei.com/product/173004/vuori-long-sleeve-strato-tech-t-shirt-mens" target="_blank" rel="nofollow" data-dimension112="ab7c9518-c96d-11f1-bbac-31a32c9b6065" data-action="Deal Block" data-label="Long Sleeve Strato Graphic Tee (Men's)" data-dimension48="Long Sleeve Strato Graphic Tee (Men's)" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c957c-c96d-11f1-8c2f-551acf235c35" data-action="Deal Block" data-label="Ponto Shorts (Men's)" data-dimension48="Ponto Shorts (Men's)" data-dimension25="$66" href="https://www.rei.com/product/135510/vuori-ponto-shorts-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1504px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="8fCbeDEGhybSmhpAfvoKvN" name="Ponto joggers" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/8fCbeDEGhybSmhpAfvoKvN-1920-80.jpg" mos="" align="middle" fullscreen="" width="1504" height="1504" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/135510/vuori-ponto-shorts-mens" target="_blank" rel="nofollow" data-dimension112="ab7c957c-c96d-11f1-8c2f-551acf235c35" data-action="Deal Block" data-label="Ponto Shorts (Men's)" data-dimension48="Ponto Shorts (Men's)" data-dimension25="$66">Ponto Shorts (Men's): was $84 now $66</a></strong><br />Designed for running or traditional workouts, these men's shorts are super lightweight, quick drying and extra durable. They come in a variety of colors and feature an elastic waistband with a drawstring and two side pockets.<a class="view-deal button" href="https://www.rei.com/product/135510/vuori-ponto-shorts-mens" target="_blank" rel="nofollow" data-dimension112="ab7c957c-c96d-11f1-8c2f-551acf235c35" data-action="Deal Block" data-label="Ponto Shorts (Men's)" data-dimension48="Ponto Shorts (Men's)" data-dimension25="$66">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c95ea-c96d-11f1-88a8-4ba0515079e6" data-action="Deal Block" data-label="Sunday Performance Joggers (Men's)" data-dimension48="Sunday Performance Joggers (Men's)" data-dimension25="$87" href="https://www.rei.com/product/135508/vuori-sunday-performance-joggers-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="75meAdFeU6zxP3XWR3ZwdL" name="Vuori joggers" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/75meAdFeU6zxP3XWR3ZwdL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/135508/vuori-sunday-performance-joggers-mens" target="_blank" rel="nofollow" data-dimension112="ab7c95ea-c96d-11f1-88a8-4ba0515079e6" data-action="Deal Block" data-label="Sunday Performance Joggers (Men's)" data-dimension48="Sunday Performance Joggers (Men's)" data-dimension25="$87">Sunday Performance Joggers (Men's): was $110 now $87</a></strong><br />You'll never want to take these pants off! They feature premium knit fabric that wicks moisture and dries fast. There's also five functional pockets, including 3 with zippers, that will keep valuables secure. They're perfect for any casual occasion and will quickly become your go-to.<a class="view-deal button" href="https://www.rei.com/product/135508/vuori-sunday-performance-joggers-mens" target="_blank" rel="nofollow" data-dimension112="ab7c95ea-c96d-11f1-88a8-4ba0515079e6" data-action="Deal Block" data-label="Sunday Performance Joggers (Men's)" data-dimension48="Sunday Performance Joggers (Men's)" data-dimension25="$87">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c964e-c96d-11f1-be8f-d544e782a7b0" data-action="Deal Block" data-label="Sedona Straight Leg Pants (Women's)" data-dimension48="Sedona Straight Leg Pants (Women's)" data-dimension25="$53" href="https://www.rei.com/product/248919/vuori-sedona-straight-leg-pants-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="5FnZvZECdE34yUWSTyiepZ" name="straight leg pants" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/5FnZvZECdE34yUWSTyiepZ-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/248919/vuori-sedona-straight-leg-pants-womens" target="_blank" rel="nofollow" data-dimension112="ab7c964e-c96d-11f1-be8f-d544e782a7b0" data-action="Deal Block" data-label="Sedona Straight Leg Pants (Women's)" data-dimension48="Sedona Straight Leg Pants (Women's)" data-dimension25="$53">Sedona Straight Leg Pants (Women's): was $108 now $53</a></strong><br />I'm adding this pair of straight leg pants to my cart ASAP! I love everything about them from their relaxed style to their versatility. I can't wait to wear them for travel days, running errands or just hanging out around the house.<a class="view-deal button" href="https://www.rei.com/product/248919/vuori-sedona-straight-leg-pants-womens" target="_blank" rel="nofollow" data-dimension112="ab7c964e-c96d-11f1-be8f-d544e782a7b0" data-action="Deal Block" data-label="Sedona Straight Leg Pants (Women's)" data-dimension48="Sedona Straight Leg Pants (Women's)" data-dimension25="$53">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c96bc-c96d-11f1-b533-617c0b52127a" data-action="Deal Block" data-label="Daydream Crew Top (Women's)" data-dimension48="Daydream Crew Top (Women's)" data-dimension25="$53" href="https://www.rei.com/product/141066/vuori-daydream-crew-top-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="FjY7FhnTftW5pCVDcAcaZa" name="Vuori deal" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/FjY7FhnTftW5pCVDcAcaZa-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/141066/vuori-daydream-crew-top-womens" target="_blank" rel="nofollow" data-dimension112="ab7c96bc-c96d-11f1-b533-617c0b52127a" data-action="Deal Block" data-label="Daydream Crew Top (Women's)" data-dimension48="Daydream Crew Top (Women's)" data-dimension25="$53">Daydream Crew Top (Women's): was $68 now $53</a></strong><br />I have my eye on this Vuori crew top that's made with a high-performance stretch fabric that wicks moisture, dries fast and blocks the sun's harmful rays. It's perfect for workouts, running errands or just hanging out around the house. <a class="view-deal button" href="https://www.rei.com/product/141066/vuori-daydream-crew-top-womens" target="_blank" rel="nofollow" data-dimension112="ab7c96bc-c96d-11f1-b533-617c0b52127a" data-action="Deal Block" data-label="Daydream Crew Top (Women's)" data-dimension48="Daydream Crew Top (Women's)" data-dimension25="$53">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c972a-c96d-11f1-a7a5-3586f5673094" data-action="Deal Block" data-label="AllTheForm Support Tank Top (Women's)" data-dimension48="AllTheForm Support Tank Top (Women's)" data-dimension25="$58" href="https://www.rei.com/product/249019/vuori-alltheform-support-tank-top-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="jNR8qhsVXiAGcNk3HmCoyT" name="tank vuori" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jNR8qhsVXiAGcNk3HmCoyT-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/249019/vuori-alltheform-support-tank-top-womens" target="_blank" rel="nofollow" data-dimension112="ab7c972a-c96d-11f1-a7a5-3586f5673094" data-action="Deal Block" data-label="AllTheForm Support Tank Top (Women's)" data-dimension48="AllTheForm Support Tank Top (Women's)" data-dimension25="$58">AllTheForm Support Tank Top (Women's): was $74 now $58</a></strong><br />This medium support top with a shelf bra is best suited to studio classes, gym sessions and everyday walking workouts, but it's so comfortable you won't want to wear anything else. Don't miss out on this $16 price cut!<a class="view-deal button" href="https://www.rei.com/product/249019/vuori-alltheform-support-tank-top-womens" target="_blank" rel="nofollow" data-dimension112="ab7c972a-c96d-11f1-a7a5-3586f5673094" data-action="Deal Block" data-label="AllTheForm Support Tank Top (Women's)" data-dimension48="AllTheForm Support Tank Top (Women's)" data-dimension25="$58">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c9806-c96d-11f1-80c7-bd9a60849d6e" data-action="Deal Block" data-label="AllTheFeels Leggings (Women's)" data-dimension48="AllTheFeels Leggings (Women's)" data-dimension25="$65" href="https://www.rei.com/product/228199/vuori-allthefeels-leggings-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="DxpmvTSCWEk3VveHKETA2U" name="leggings" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/DxpmvTSCWEk3VveHKETA2U-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/228199/vuori-allthefeels-leggings-womens" target="_blank" rel="nofollow" data-dimension112="ab7c9806-c96d-11f1-80c7-bd9a60849d6e" data-action="Deal Block" data-label="AllTheFeels Leggings (Women's)" data-dimension48="AllTheFeels Leggings (Women's)" data-dimension25="$65">AllTheFeels Leggings (Women's): was $110 now $65</a></strong><br />Designed for yoga, lounging or anything in  between, these pants feature buttery soft fabric with a cloud-like feel. They're lightweight and stretchy so you can enjoy a full range of motion while sporting them. <a class="view-deal button" href="https://www.rei.com/product/228199/vuori-allthefeels-leggings-womens" target="_blank" rel="nofollow" data-dimension112="ab7c9806-c96d-11f1-80c7-bd9a60849d6e" data-action="Deal Block" data-label="AllTheFeels Leggings (Women's)" data-dimension48="AllTheFeels Leggings (Women's)" data-dimension25="$65">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c9874-c96d-11f1-8d87-7399264b521e" data-action="Deal Block" data-label="Alpine Jacket (Women's)" data-dimension48="Alpine Jacket (Women's)" data-dimension25="$93" href="https://www.rei.com/product/252323/vuori-alpine-jacket-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1803px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="cq7sUCDGx753aFkJ98baq9" name="alpine jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/cq7sUCDGx753aFkJ98baq9-1920-80.jpg" mos="" align="middle" fullscreen="" width="1803" height="1803" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/252323/vuori-alpine-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c9874-c96d-11f1-8d87-7399264b521e" data-action="Deal Block" data-label="Alpine Jacket (Women's)" data-dimension48="Alpine Jacket (Women's)" data-dimension25="$93">Alpine Jacket (Women's): was $188 now $93</a></strong><br />This cute and cozy jacket is 51% off and the perfect layer for fall. Crafted from 100% recycled fleece, the jacket has an oversize fit and zip hand pockets. <a class="view-deal button" href="https://www.rei.com/product/252323/vuori-alpine-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c9874-c96d-11f1-8d87-7399264b521e" data-action="Deal Block" data-label="Alpine Jacket (Women's)" data-dimension48="Alpine Jacket (Women's)" data-dimension25="$93">View Deal</a></p></div><h3 class="article-body__section" id="section-more-deals"><span>More Deals</span></h3><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Running&amp;view_mode=savings_squad&amp;widget_title=Top+Deals+Handpicked+by+Our+Editors&amp;widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&amp;bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                if (externalUrl) {                   if (seenUrls.has(externalUrl)) return;                  seenUrls.add(externalUrl);                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || '',                   authorName: article.articleauthortext ? article.articleauthortext[0] : (article.articleauthor ? article.articleauthor[0] : ''),                   authorRole: article.articleauthorrole ? article.articleauthorrole[0] : '',                   authorImage: article.articleauthormedia ? article.articleauthormedia[0] : '',                   documentUrl: article.documenturl ? article.documenturl[0] : '',                   modifiedDate: article.contentmodifieddate || article.modifieddate || ''                });             });          });                    const airedaleBrandsList = Object.keys(overallBrandsCounts).map(b => ({              formatted_value: b,              count: overallBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 40px; min-height: 40px;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 36px; min-height: 36px;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness/patagonia-arcteryx-and-the-north-face-are-up-to-50-percent-off-at-rei-27-best-apparel-deals-for-fall</link>
                                                                            <description>
                            <![CDATA[ REI's fall sale just dropped. Save up to 50% on the best outdoor apparel and gear. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">Gco6KHDbJRywY63Nk5TKXY</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/EBNi5gMAq9qNuUfC3tLa7Q-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 16 Oct 2026 15:07:18 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Fitness]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                                    <dc:creator><![CDATA[ Olivia Halevy ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/YAg7Fmh9dGKbg3hULBMWiU-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Olivia is a Deals Writer at Tom’s Guide. She loves all things lifestyle, shopping and sourcing the best deals from some of the top brands, retailers and websites around. From fashion and beauty to smart home and tech, she has an eye for finding practical, stylish, and reasonably-priced items that help make life simpler (and a little more aesthetically-pleasing).&amp;nbsp;Olivia has over five years of experience writing lifestyle, commerce, and branded content for &lt;a href=&quot;http://patch.com/&quot;&gt;Patch.com&lt;/a&gt;. She&#039;s covered major shopping holidays like Amazon Prime Day, Black Friday and Cyber Monday. In her free time, she enjoys trying out new exercise classes, binge-watching the latest viral TV shows, cooking, spending time with family and taking long walks with her dog, Gus.&amp;nbsp;&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/EBNi5gMAq9qNuUfC3tLa7Q-1920-80.jpg">
                                                            <media:credit><![CDATA[REI / edited by Gemini]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[REI sale]]></media:description>                                                            <media:text><![CDATA[REI sale]]></media:text>
                                <media:title type="plain"><![CDATA[REI sale]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/EBNi5gMAq9qNuUfC3tLa7Q-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Now that temperatures are starting to drop, investing in some high-quality outerwear is a must. While it’s worth spending a little extra on pieces built to last, the good news is you don’t have to break the bank to find something great. </p><p>Case in point: <a href="https://www.rei.com/f/scd-deals" target="_blank" rel="nofollow">REI's sale section is packed to the brim with impressive deals</a> from top brands like Patagonia, The North Face, Arc'teryx and more. The outdoor retailer is offering discounts of up to 50% on lightweight jackets, fleeces, hiking gear and more. For instance, <a href="https://www.rei.com/product/143470/patagonia-houdini-jacket-mens" target="_blank" rel="nofollow">the popular Patagonia Houdini Jacket is down to just $82</a> and is the perfect layer for fall adventures.</p><p>There's plenty more deals where that came from! Below, I've rounded up my favorite REI styles. Keep scrolling to check out the deals that are actually worth shopping for fall. </p><h3 class="article-body__section" id="section-quick-links"><span>Quick Links</span></h3><ul><li><a href="https://www.rei.com/f/scd-deals" target="_blank" rel="nofollow"><strong>shop REI's fall sale</strong></a></li><li><strong>Camping gear: </strong><a href="https://www.rei.com/c/camping-and-hiking/f/scd-deals" target="_blank" rel="nofollow"><strong>up to 30% off</strong></a></li><li><strong>Vuori: </strong><a href="https://www.rei.com/b/vuori/f/scd-deals?" target="_blank" rel="nofollow"><strong>up to 40% off</strong></a></li><li><strong>Arc'teryx: </strong><a href="https://www.rei.com/b/arcteryx/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;sort=min-price&amp;r=f%3Bb" target="_blank" rel="nofollow"><strong>apparel from $24</strong></a></li><li><strong>Columbia: </strong><a href="https://www.rei.com/b/columbia/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;sort=min-price&amp;irclickid=3KjxOUTuLxyKWYwT3BUaGy3DUkp2c0Uto0pyw40" target="_blank" rel="nofollow"><strong>apparel from $14</strong></a></li><li><strong>Patagonia: </strong><a href="https://www.rei.com/b/patagonia/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;r=f%3Bb&amp;sort=min-price" target="_blank" rel="nofollow"><strong>apparel/accessories from $15</strong></a></li><li><strong>Marmot: </strong><a href="https://www.rei.com/b/marmot/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;sort=min-price&amp;r=f%3Bb" target="_blank" rel="nofollow"><strong>apparel from $15</strong></a></li><li><strong>The North Face: </strong><a href="https://www.rei.com/b/the-north-face/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;r=f%3Bb&amp;sort=min-price" target="_blank" rel="nofollow"><strong>apparel from $16</strong></a></li><li><strong>Yeti: </strong><a href="https://www.rei.com/b/yeti/f/scd-deals?" target="_blank" rel="nofollow"><strong>water bottles from $17</strong></a></li><li><strong>Adidas: </strong><a href="https://www.rei.com/b/adidas/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;r=f%3Bb&amp;sort=min-price" target="_blank" rel="nofollow"><strong>sports bras/shirts from $19</strong></a></li><li><strong>Saucony: </strong><a href="https://www.rei.com/b/saucony/f/scd-deals?ir=deals%3ASee+All+Deals&amp;pagesize=90&amp;sort=min-price&amp;r=f%3Bb" target="_blank" rel="nofollow"><strong>running gear from $46</strong></a><strong></strong></li></ul><h3 class="article-body__section" id="section-top-rei-deals"><span>Top REI Deals</span></h3><div class="product"><a data-dimension112="ab7c8b68-c96d-11f1-ba62-9fc21c58633d" data-action="Deal Block" data-label="Houdini Jacket (Men's)" data-dimension48="Houdini Jacket (Men's)" data-dimension25="$82" href="https://www.rei.com/product/143470/patagonia-houdini-jacket-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:588px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="8GQeT4DV45yR8hUW8QhMEC" name="REI Patagonia jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/8GQeT4DV45yR8hUW8QhMEC-1920-80.jpg" mos="" align="middle" fullscreen="" width="588" height="588" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/143470/patagonia-houdini-jacket-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8b68-c96d-11f1-ba62-9fc21c58633d" data-action="Deal Block" data-label="Houdini Jacket (Men's)" data-dimension48="Houdini Jacket (Men's)" data-dimension25="$82">Houdini Jacket (Men's): was $109 now $82</a></strong><br />Lightweight and compact enough to stuff into a back pocket yet warm and weather-resistant enough to keep you dry and comfy in moderate rain and chilliness, the Patagonia Houdini really lives up to its magical name.  <a class="view-deal button" href="https://www.rei.com/product/143470/patagonia-houdini-jacket-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8b68-c96d-11f1-ba62-9fc21c58633d" data-action="Deal Block" data-label="Houdini Jacket (Men's)" data-dimension48="Houdini Jacket (Men's)" data-dimension25="$82">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c8bd6-c96d-11f1-8d0b-9f4b4962e70c" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$139" href="https://www.rei.com/product/C01854/the-north-face-aconcagua-3-down-jacket-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="3NRirLjHRfkq2GuUVcaUTa" name="The North Face Jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/3NRirLjHRfkq2GuUVcaUTa-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01854/the-north-face-aconcagua-3-down-jacket-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8bd6-c96d-11f1-8d0b-9f4b4962e70c" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$139">Aconcagua 3 Jacket (Men's): was $200 now $139</a></strong><br />This lightweight puffer blends recycled down with synthetic insulation for maximum warmth and weather resistance in a tidy, easy-to-stow package. Zonal sheet insulation and a water-repellant finish round out the feature set.<a class="view-deal button" href="https://www.rei.com/product/C01854/the-north-face-aconcagua-3-down-jacket-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8bd6-c96d-11f1-8d0b-9f4b4962e70c" data-action="Deal Block" data-label="Aconcagua 3 Jacket (Men's)" data-dimension48="Aconcagua 3 Jacket (Men's)" data-dimension25="$139">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c8c44-c96d-11f1-aa6b-d9293a4bf4b6" data-action="Deal Block" data-label="Beta SL Jacket (Men's)" data-dimension48="Beta SL Jacket (Men's)" data-dimension25="$299" href="https://www.rei.com/product/235112/arcteryx-beta-sl-jacket-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="qb97kzq9mCRC8aoRkEXVCX" name="Arc'teryx Beta" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/qb97kzq9mCRC8aoRkEXVCX-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/235112/arcteryx-beta-sl-jacket-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8c44-c96d-11f1-aa6b-d9293a4bf4b6" data-action="Deal Block" data-label="Beta SL Jacket (Men's)" data-dimension48="Beta SL Jacket (Men's)" data-dimension25="$299">Beta SL Jacket (Men's): was $500 now $299</a></strong><br />Lightweight, comfortable and breathable, this durable waterproof and windproof jacket will protect you from the elements without sacrificing features or packability. It's a great option for layering or wearing on its own. <a class="view-deal button" href="https://www.rei.com/product/235112/arcteryx-beta-sl-jacket-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8c44-c96d-11f1-aa6b-d9293a4bf4b6" data-action="Deal Block" data-label="Beta SL Jacket (Men's)" data-dimension48="Beta SL Jacket (Men's)" data-dimension25="$299">View Deal</a></p></div><h3 class="article-body__section" id="section-patagonia"><span>Patagonia</span></h3><div class="product"><a data-dimension112="ab7c8d20-c96d-11f1-a6c9-6fc1636449ae" data-action="Deal Block" data-label="Baggies Shorts (Men’s)" data-dimension48="Baggies Shorts (Men’s)" data-dimension25="$54" href="https://www.rei.com/product/242831/patagonia-baggies-5-shorts-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1504px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="JtXgyevXrT5SUBGhvhBYQF" name="patagonia baggies" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/JtXgyevXrT5SUBGhvhBYQF-1920-80.jpg" mos="" align="middle" fullscreen="" width="1504" height="1504" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/242831/patagonia-baggies-5-shorts-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8d20-c96d-11f1-a6c9-6fc1636449ae" data-action="Deal Block" data-label="Baggies Shorts (Men’s)" data-dimension48="Baggies Shorts (Men’s)" data-dimension25="$54">Baggies Shorts (Men’s): was $69 now $54</a></strong><br />Summer may be officially over, but Patagonia's Baggie shorts are suitable for both inside and out of the water. And as the brand are clearing out their end-of-season styles, you can get these shorts for as low as $54.<a class="view-deal button" href="https://www.rei.com/product/242831/patagonia-baggies-5-shorts-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8d20-c96d-11f1-a6c9-6fc1636449ae" data-action="Deal Block" data-label="Baggies Shorts (Men’s)" data-dimension48="Baggies Shorts (Men’s)" data-dimension25="$54">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c8d8e-c96d-11f1-b5b4-03a9de12bf9f" data-action="Deal Block" data-label="Outdoor Everyday Pants (Women's)" data-dimension48="Outdoor Everyday Pants (Women's)" data-dimension25="$68" href="https://www.rei.com/product/228412/patagonia-outdoor-everyday-pants-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="zoeCcCwPahdqAedoN2ztbX" name="pants" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/zoeCcCwPahdqAedoN2ztbX-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/228412/patagonia-outdoor-everyday-pants-womens" target="_blank" rel="nofollow" data-dimension112="ab7c8d8e-c96d-11f1-b5b4-03a9de12bf9f" data-action="Deal Block" data-label="Outdoor Everyday Pants (Women's)" data-dimension48="Outdoor Everyday Pants (Women's)" data-dimension25="$68">Outdoor Everyday Pants (Women's): was $99 now $68</a></strong><br />Although they look like sweatpants, the Patagonia Outdoor Everyday Pants are ideal for hikes and outdoor activities. As they're wide-legged, they're super comfortable, and are even water-repellant. They're on sale in three different colors.<a class="view-deal button" href="https://www.rei.com/product/228412/patagonia-outdoor-everyday-pants-womens" target="_blank" rel="nofollow" data-dimension112="ab7c8d8e-c96d-11f1-b5b4-03a9de12bf9f" data-action="Deal Block" data-label="Outdoor Everyday Pants (Women's)" data-dimension48="Outdoor Everyday Pants (Women's)" data-dimension25="$68">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c8dfc-c96d-11f1-9fb7-6da03d377a2b" data-action="Deal Block" data-label="P-6 Logo Uprisal Hoody (Unisex)" data-dimension48="P-6 Logo Uprisal Hoody (Unisex)" data-dimension25="$71" href="https://www.rei.com/product/191626/patagonia-p-6-logo-uprisal-hoody" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1707px;"><p class="vanilla-image-block" style="padding-top:117.16%;"><img id="AxhSkgAYP5VCo4UWcfgBNi" name="Patagonia hoodie" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/AxhSkgAYP5VCo4UWcfgBNi-1920-80.jpg" mos="" align="middle" fullscreen="" width="1707" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/191626/patagonia-p-6-logo-uprisal-hoody" target="_blank" rel="nofollow" data-dimension112="ab7c8dfc-c96d-11f1-9fb7-6da03d377a2b" data-action="Deal Block" data-label="P-6 Logo Uprisal Hoody (Unisex)" data-dimension48="P-6 Logo Uprisal Hoody (Unisex)" data-dimension25="$71">P-6 Logo Uprisal Hoody (Unisex): was $95 now $71</a></strong><br />This is such a classic versatile hoody, I can't quite believe it's discounted in three colors. This is the kind of sweater that never goes out of style. This hoody is made from 30 plastic bottles, so you know you're wearing something that is benefitting the planet.  <a class="view-deal button" href="https://www.rei.com/product/191626/patagonia-p-6-logo-uprisal-hoody" target="_blank" rel="nofollow" data-dimension112="ab7c8dfc-c96d-11f1-9fb7-6da03d377a2b" data-action="Deal Block" data-label="P-6 Logo Uprisal Hoody (Unisex)" data-dimension48="P-6 Logo Uprisal Hoody (Unisex)" data-dimension25="$71">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c8e6a-c96d-11f1-93be-959557990a53" data-action="Deal Block" data-label="Ahnya Pullover (Women's)" data-dimension48="Ahnya Pullover (Women's)" data-dimension25="$93" href="https://www.rei.com/product/250042/patagonia-ahnya-full-zip-hoody-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1600px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="8Ja4UguKzZauzQ2r3qNtGm" name="patagonia" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/8Ja4UguKzZauzQ2r3qNtGm-1920-80.jpg" mos="" align="middle" fullscreen="" width="1600" height="1600" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/250042/patagonia-ahnya-full-zip-hoody-womens" target="_blank" rel="nofollow" data-dimension112="ab7c8e6a-c96d-11f1-93be-959557990a53" data-action="Deal Block" data-label="Ahnya Pullover (Women's)" data-dimension48="Ahnya Pullover (Women's)" data-dimension25="$93">Ahnya Pullover (Women's): was $135 now $93</a></strong><br />Nothing says fall apparel like a lightweight pullover. The sweatshirt is made with Regenerative Organic Certified cotton and recycled polyester fleece and spandex, with front pockets and rib-knit cuffs. It's perfect for throwing over a tee or wearing under a jacket.<a class="view-deal button" href="https://www.rei.com/product/250042/patagonia-ahnya-full-zip-hoody-womens" target="_blank" rel="nofollow" data-dimension112="ab7c8e6a-c96d-11f1-93be-959557990a53" data-action="Deal Block" data-label="Ahnya Pullover (Women's)" data-dimension48="Ahnya Pullover (Women's)" data-dimension25="$93">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c8ece-c96d-11f1-b064-adc37fb2618e" data-action="Deal Block" data-label="Houdini Half-zip" data-dimension48="Houdini Half-zip" data-dimension25="$100" href="https://www.rei.com/product/228564/patagonia-houdini-stash-half-zip-jacket-mens?color=CASCADE%2520GREEN" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1090px;"><p class="vanilla-image-block" style="padding-top:112.75%;"><img id="Ae9C3N28VXVi824kshL69a" name="Screenshot 2026-06-15 at 9.10.35 PM" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Ae9C3N28VXVi824kshL69a-1920-80.png" mos="" align="middle" fullscreen="" width="1090" height="1229" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p>The Patagonia Houdini Half-Zip is nothing short of pure magic. This back-pocket-packable pull-over weighs about as much as a deck of playing cards, yet offers seriously solid protection from the rain, wind and chill.<a class="view-deal button" href="https://www.rei.com/product/228564/patagonia-houdini-stash-half-zip-jacket-mens?color=CASCADE%2520GREEN" target="_blank" rel="nofollow" data-dimension112="ab7c8ece-c96d-11f1-b064-adc37fb2618e" data-action="Deal Block" data-label="Houdini Half-zip" data-dimension48="Houdini Half-zip" data-dimension25="$100">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c8f3c-c96d-11f1-a1d1-b9b071c8c123" data-action="Deal Block" data-label="R1 Pullover - Women's" data-dimension48="R1 Pullover - Women's" data-dimension25="$107" href="https://www.rei.com/product/242323/patagonia-r1-pullover-womens" 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="bre5ZuSFLvwfm5qxrkvwTm" name="patagonia r1 pullover" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/bre5ZuSFLvwfm5qxrkvwTm-1920-80.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/242323/patagonia-r1-pullover-womens" target="_blank" rel="nofollow" data-dimension112="ab7c8f3c-c96d-11f1-a1d1-b9b071c8c123" data-action="Deal Block" data-label="R1 Pullover - Women's" data-dimension48="R1 Pullover - Women's" data-dimension25="$107">R1 Pullover - Women's: was $155 now $107</a></strong><br />The Patagonia R1 Pullover is a midlayer, meaning it's intended to be worn between a thermal base layer and an outer waterproof or windproof jacket like the Patagonia Houdini. Right now, it's <a class="view-deal button" href="https://www.rei.com/product/242323/patagonia-r1-pullover-womens" target="_blank" rel="nofollow" data-dimension112="ab7c8f3c-c96d-11f1-a1d1-b9b071c8c123" data-action="Deal Block" data-label="R1 Pullover - Women's" data-dimension48="R1 Pullover - Women's" data-dimension25="$107">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c8faa-c96d-11f1-9c9f-0d6a1312332c" data-action="Deal Block" data-label="Daily Snap-T Pullover (Men's)" data-dimension48="Daily Snap-T Pullover (Men's)" data-dimension25="$124" href="https://www.rei.com/product/C01345/patagonia-daily-snap-t-pullover-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1560px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="WGXNCXSCXiBba8uzoeFYnS" name="Patagonia Snap T" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/WGXNCXSCXiBba8uzoeFYnS-1920-80.jpg" mos="" align="middle" fullscreen="" width="1560" height="1560" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01345/patagonia-daily-snap-t-pullover-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8faa-c96d-11f1-9c9f-0d6a1312332c" data-action="Deal Block" data-label="Daily Snap-T Pullover (Men's)" data-dimension48="Daily Snap-T Pullover (Men's)" data-dimension25="$124">Daily Snap-T Pullover (Men's): was $179 now $124</a></strong><br />This fleece is perfect to wear at the campsite during chilly evenings, or on early morning trails. The Daily Snap-T Pullover is made from 100% regenerative organic cotton as well. It's available in every single size, so you'll be able to find your perfect fit. <a class="view-deal button" href="https://www.rei.com/product/C01345/patagonia-daily-snap-t-pullover-mens" target="_blank" rel="nofollow" data-dimension112="ab7c8faa-c96d-11f1-9c9f-0d6a1312332c" data-action="Deal Block" data-label="Daily Snap-T Pullover (Men's)" data-dimension48="Daily Snap-T Pullover (Men's)" data-dimension25="$124">View Deal</a></p></div><h3 class="article-body__section" id="section-the-north-face"><span>The North Face</span></h3><div class="product"><a data-dimension112="ab7c907c-c96d-11f1-81f0-6f15033afcf2" data-action="Deal Block" data-label="Glacier Fleece Quarter-Zip Jacket (Men's)" data-dimension48="Glacier Fleece Quarter-Zip Jacket (Men's)" data-dimension25="$45" href="https://www.rei.com/product/C11727/the-north-face-glacier-fleece-quarter-zip-jacket-mens?color=DUSK%2520BLUE" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1452px;"><p class="vanilla-image-block" style="padding-top:100.07%;"><img id="yvbgf7cVFY9masQPhTAnVU" name="TNF-02b" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/yvbgf7cVFY9masQPhTAnVU-1920-80.jpg" mos="" align="middle" fullscreen="" width="1452" height="1453" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C11727/the-north-face-glacier-fleece-quarter-zip-jacket-mens?color=DUSK%2520BLUE" target="_blank" rel="nofollow" data-dimension112="ab7c907c-c96d-11f1-81f0-6f15033afcf2" data-action="Deal Block" data-label="Glacier Fleece Quarter-Zip Jacket (Men's)" data-dimension48="Glacier Fleece Quarter-Zip Jacket (Men's)" data-dimension25="$45">Glacier Fleece Quarter-Zip Jacket (Men's): was $70 now $45</a></strong><br />The Glacier Fleece Quarter-Zip is a highly versatile garment that works both as an outer-layer and as a mid-layer, depending on temps. Plus, this deal is on the Dusk Blue variant, which I find very easy on the eyes. <a class="view-deal button" href="https://www.rei.com/product/C11727/the-north-face-glacier-fleece-quarter-zip-jacket-mens?color=DUSK%2520BLUE" target="_blank" rel="nofollow" data-dimension112="ab7c907c-c96d-11f1-81f0-6f15033afcf2" data-action="Deal Block" data-label="Glacier Fleece Quarter-Zip Jacket (Men's)" data-dimension48="Glacier Fleece Quarter-Zip Jacket (Men's)" data-dimension25="$45">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c90ea-c96d-11f1-8e86-af29db5f09ec" data-action="Deal Block" data-label="DotKnit Thermal ¼-Zip (Women's)" data-dimension48="DotKnit Thermal ¼-Zip (Women's)" data-dimension25="$64" href="https://www.rei.com/product/254013/the-north-face-dotknit-thermal-quarter-zip-pullover-womens?color=MIDNIGHT%2520PETROL" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:576px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="JkvuGYs7dyyBgbeoS9VyUF" name="The North Face dotknot" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/JkvuGYs7dyyBgbeoS9VyUF-1920-80.jpg" mos="" align="middle" fullscreen="" width="576" height="576" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/254013/the-north-face-dotknit-thermal-quarter-zip-pullover-womens?color=MIDNIGHT%2520PETROL" target="_blank" rel="nofollow" data-dimension112="ab7c90ea-c96d-11f1-8e86-af29db5f09ec" data-action="Deal Block" data-label="DotKnit Thermal ¼-Zip (Women's)" data-dimension48="DotKnit Thermal ¼-Zip (Women's)" data-dimension25="$64">DotKnit Thermal ¼-Zip (Women's): was $90 now $64</a></strong><br />If you're a runner, you need this ¼-zip for the colder months. Not only does it help regulate body temperature with its innovative insulating fabric, it also actively moves moisture away from the body.<a class="view-deal button" href="https://www.rei.com/product/254013/the-north-face-dotknit-thermal-quarter-zip-pullover-womens?color=MIDNIGHT%2520PETROL" target="_blank" rel="nofollow" data-dimension112="ab7c90ea-c96d-11f1-8e86-af29db5f09ec" data-action="Deal Block" data-label="DotKnit Thermal ¼-Zip (Women's)" data-dimension48="DotKnit Thermal ¼-Zip (Women's)" data-dimension25="$64">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c9158-c96d-11f1-b77b-ef519819e59b" data-action="Deal Block" data-label="Osito Lux Jacket (Women's)" data-dimension48="Osito Lux Jacket (Women's)" data-dimension25="$65" href="https://www.rei.com/product/250475/the-north-face-osito-lux-jacket-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1290px;"><p class="vanilla-image-block" style="padding-top:116.28%;"><img id="MZdvPZM2QPb9UsJtviZ5GJ" name="Osito Lux Jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/MZdvPZM2QPb9UsJtviZ5GJ-1920-80.jpg" mos="" align="middle" fullscreen="" width="1290" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/250475/the-north-face-osito-lux-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c9158-c96d-11f1-b77b-ef519819e59b" data-action="Deal Block" data-label="Osito Lux Jacket (Women's)" data-dimension48="Osito Lux Jacket (Women's)" data-dimension25="$65">Osito Lux Jacket (Women's): was $130 now $65</a></strong><br />The super soft Osito Jacket is made with a supersoft high-pile fleece and provides instant, lightweight warmth. It has a rib-knit collar, hem and cuffs for better warmth retention in chilly weather.<a class="view-deal button" href="https://www.rei.com/product/250475/the-north-face-osito-lux-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c9158-c96d-11f1-b77b-ef519819e59b" data-action="Deal Block" data-label="Osito Lux Jacket (Women's)" data-dimension48="Osito Lux Jacket (Women's)" data-dimension25="$65">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c91c6-c96d-11f1-8a12-073a01b255d7" data-action="Deal Block" data-label="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension48="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension25="$74" href="https://www.rei.com/product/C00697/the-north-face-yumiori-off-peak-full-zip-jacket-womens" 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="vamU4Ky2CB4QQda8nfrvm4" name="the north face yumiori jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/vamU4Ky2CB4QQda8nfrvm4-1920-80.jpg" mos="" align="middle" fullscreen="" width="1000" height="1000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C00697/the-north-face-yumiori-off-peak-full-zip-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c91c6-c96d-11f1-8a12-073a01b255d7" data-action="Deal Block" data-label="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension48="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension25="$74">Yumiori Off Peak Full-Zip Jacket - Women's: was $150 now $74</a></strong><br />The North Face's Yumiori fleece is a perfect hiking-slash-everyday fleece. Smartphones fit snugly into the chest pocket, one zipper even doubles as a hair tie, and it's finished with durable water repellent. Three colors are available at 51% off in sizes S-XL.<a class="view-deal button" href="https://www.rei.com/product/C00697/the-north-face-yumiori-off-peak-full-zip-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c91c6-c96d-11f1-8a12-073a01b255d7" data-action="Deal Block" data-label="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension48="Yumiori Off Peak Full-Zip Jacket - Women's" data-dimension25="$74">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c922a-c96d-11f1-b840-136b8c58f73c" data-action="Deal Block" data-label="Kikash Wind Jacket (Women's)" data-dimension48="Kikash Wind Jacket (Women's)" data-dimension25="$75" href="https://www.rei.com/product/254048/the-north-face-kikash-wind-jacket-womens" 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="euVM6xCmm2F8CfG6fPp57T" name="Kikash jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/euVM6xCmm2F8CfG6fPp57T-1920-80.jpg" mos="" align="middle" fullscreen="" width="1500" height="1500" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/254048/the-north-face-kikash-wind-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c922a-c96d-11f1-b840-136b8c58f73c" data-action="Deal Block" data-label="Kikash Wind Jacket (Women's)" data-dimension48="Kikash Wind Jacket (Women's)" data-dimension25="$75">Kikash Wind Jacket (Women's): was $150 now $75</a></strong><br />The Kikash Wind Jacket is built for those days when the wind won't quit. The durable nylon fabric shrugs off mountain gusts while keeping you mobile, and reflective details add crucial visibility for early starts or late finishes. The secure zip pockets and snug elastic hem make it a reliable companion for unpredictable conditions.<a class="view-deal button" href="https://www.rei.com/product/254048/the-north-face-kikash-wind-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c922a-c96d-11f1-b840-136b8c58f73c" data-action="Deal Block" data-label="Kikash Wind Jacket (Women's)" data-dimension48="Kikash Wind Jacket (Women's)" data-dimension25="$75">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c9298-c96d-11f1-a652-1be06bb24e0a" data-action="Deal Block" data-label="Alta Vista Rain Jacket (Women's)" data-dimension48="Alta Vista Rain Jacket (Women's)" data-dimension25="$79" href="https://www.rei.com/product/242819/the-north-face-alta-vista-rain-jacket-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1772px;"><p class="vanilla-image-block" style="padding-top:112.87%;"><img id="dkBbNBgcHs4GBuZg9YpfQk" name="image" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/dkBbNBgcHs4GBuZg9YpfQk-1920-80.png" mos="" align="middle" fullscreen="" width="1772" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/242819/the-north-face-alta-vista-rain-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c9298-c96d-11f1-a652-1be06bb24e0a" data-action="Deal Block" data-label="Alta Vista Rain Jacket (Women's)" data-dimension48="Alta Vista Rain Jacket (Women's)" data-dimension25="$79">Alta Vista Rain Jacket (Women's): was $160 now $79</a></strong><br />The North Face Alta Vista Rain Jacket is the kind of shell you’ll thank yourself for when the rain hits mid-hike or dog walk. It’s breathable, practical, and full of easy-access pockets. It looks great outdoors and just as good around town. I never travel without a waterproof jacket for fall city breaks, and this one fits the bill perfectly.<a class="view-deal button" href="https://www.rei.com/product/242819/the-north-face-alta-vista-rain-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c9298-c96d-11f1-a652-1be06bb24e0a" data-action="Deal Block" data-label="Alta Vista Rain Jacket (Women's)" data-dimension48="Alta Vista Rain Jacket (Women's)" data-dimension25="$79">View Deal</a></p></div><h3 class="article-body__section" id="section-arc-teryx"><span>Arc'teryx</span></h3><div class="product"><a data-dimension112="ab7c936a-c96d-11f1-8d8c-33f7642b9c57" data-action="Deal Block" data-label="Norvan Downword Logo T-Shirt (Men's)" data-dimension48="Norvan Downword Logo T-Shirt (Men's)" data-dimension25="$44" href="https://www.rei.com/product/C01313/arcteryx-norvan-downword-logo-t-shirt-mens?color=MANTIS%252FTATSU" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="PWCsPHixKKo3VfnePAiX9Z" name="Arc'teryx tee" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/PWCsPHixKKo3VfnePAiX9Z-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01313/arcteryx-norvan-downword-logo-t-shirt-mens?color=MANTIS%252FTATSU" target="_blank" rel="nofollow" data-dimension112="ab7c936a-c96d-11f1-8d8c-33f7642b9c57" data-action="Deal Block" data-label="Norvan Downword Logo T-Shirt (Men's)" data-dimension48="Norvan Downword Logo T-Shirt (Men's)" data-dimension25="$44">Norvan Downword Logo T-Shirt (Men's): was $90 now $44</a></strong><br />The<strong> </strong>Norvan Downword T-Shirt is a lightweight moisture-wicking tee designed for trail running but is an excellent tee for any outdoor adventure. It is water resistant and has an 'anti-odor' finish to keep you fresh on the trails. Take advantage of this deal now and save big!<a class="view-deal button" href="https://www.rei.com/product/C01313/arcteryx-norvan-downword-logo-t-shirt-mens?color=MANTIS%252FTATSU" target="_blank" rel="nofollow" data-dimension112="ab7c936a-c96d-11f1-8d8c-33f7642b9c57" data-action="Deal Block" data-label="Norvan Downword Logo T-Shirt (Men's)" data-dimension48="Norvan Downword Logo T-Shirt (Men's)" data-dimension25="$44">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c93d8-c96d-11f1-bc42-817072f6b981" data-action="Deal Block" data-label="Sima Hoody (Men's)" data-dimension48="Sima Hoody (Men's)" data-dimension25="$119" href="https://www.rei.com/product/C01372/arcteryx-sima-hoody-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1999px;"><p class="vanilla-image-block" style="padding-top:100.05%;"><img id="7ALJ3myuTiT2XsP4zXyHWg" name="Arc'teryx Sima" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/7ALJ3myuTiT2XsP4zXyHWg-1920-80.jpg" mos="" align="middle" fullscreen="" width="1999" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01372/arcteryx-sima-hoody-mens" target="_blank" rel="nofollow" data-dimension112="ab7c93d8-c96d-11f1-bc42-817072f6b981" data-action="Deal Block" data-label="Sima Hoody (Men's)" data-dimension48="Sima Hoody (Men's)" data-dimension25="$119">Sima Hoody (Men's): was $160 now $119</a></strong><br />This chic zip-up jacket is designed with backpackers and hikers in mind. Weighing just over six ounces, it's made from synthetic fabric with UPF 50+ sun protection. Nice and breathable, the fabric is also moisture-wicking to keep you dry.<a class="view-deal button" href="https://www.rei.com/product/C01372/arcteryx-sima-hoody-mens" target="_blank" rel="nofollow" data-dimension112="ab7c93d8-c96d-11f1-bc42-817072f6b981" data-action="Deal Block" data-label="Sima Hoody (Men's)" data-dimension48="Sima Hoody (Men's)" data-dimension25="$119">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c943c-c96d-11f1-b867-65f1e96cb788" data-action="Deal Block" data-label="Squamish Hoody - Men's" data-dimension48="Squamish Hoody - Men's" data-dimension25="$119" href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="gU2HZNV4QV8x48bVFDMoVL" name="Arc'teryx Squamish" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/gU2HZNV4QV8x48bVFDMoVL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow" data-dimension112="ab7c943c-c96d-11f1-b867-65f1e96cb788" data-action="Deal Block" data-label="Squamish Hoody - Men's" data-dimension48="Squamish Hoody - Men's" data-dimension25="$119">Squamish Hoody - Men's: was $200 now $119</a></strong><br />The Arc'teryx Squamish Hoody is completely windproof and finished with DWR, making it a versatile outer layer for those nippy wintry hikes. There's even a capped hood for keeping your face dry. Currently three colors from XS-XL are discounted.<a class="view-deal button" href="https://www.rei.com/product/C01005/arcteryx-squamish-hoody-mens" target="_blank" rel="nofollow" data-dimension112="ab7c943c-c96d-11f1-b867-65f1e96cb788" data-action="Deal Block" data-label="Squamish Hoody - Men's" data-dimension48="Squamish Hoody - Men's" data-dimension25="$119">View Deal</a></p></div><h3 class="article-body__section" id="section-vuori"><span>Vuori</span></h3><div class="product"><a data-dimension112="ab7c9518-c96d-11f1-bbac-31a32c9b6065" data-action="Deal Block" data-label="Long Sleeve Strato Graphic Tee (Men's)" data-dimension48="Long Sleeve Strato Graphic Tee (Men's)" data-dimension25="$39" href="https://www.rei.com/product/173004/vuori-long-sleeve-strato-tech-t-shirt-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="Q2apw9UBKpntczusMwSp9n" name="Strato tee" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/Q2apw9UBKpntczusMwSp9n-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/173004/vuori-long-sleeve-strato-tech-t-shirt-mens" target="_blank" rel="nofollow" data-dimension112="ab7c9518-c96d-11f1-bbac-31a32c9b6065" data-action="Deal Block" data-label="Long Sleeve Strato Graphic Tee (Men's)" data-dimension48="Long Sleeve Strato Graphic Tee (Men's)" data-dimension25="$39">Long Sleeve Strato Graphic Tee (Men's): was $69 now $39</a></strong><br />You can always use an extra long sleeve tee in your wardrobe — and this one will quickly become your favorite. This super soft piece of workout gear will be your go-to during your workouts, weekend adventures and lounge sessions. <a class="view-deal button" href="https://www.rei.com/product/173004/vuori-long-sleeve-strato-tech-t-shirt-mens" target="_blank" rel="nofollow" data-dimension112="ab7c9518-c96d-11f1-bbac-31a32c9b6065" data-action="Deal Block" data-label="Long Sleeve Strato Graphic Tee (Men's)" data-dimension48="Long Sleeve Strato Graphic Tee (Men's)" data-dimension25="$39">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c957c-c96d-11f1-8c2f-551acf235c35" data-action="Deal Block" data-label="Ponto Shorts (Men's)" data-dimension48="Ponto Shorts (Men's)" data-dimension25="$66" href="https://www.rei.com/product/135510/vuori-ponto-shorts-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1504px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="8fCbeDEGhybSmhpAfvoKvN" name="Ponto joggers" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/8fCbeDEGhybSmhpAfvoKvN-1920-80.jpg" mos="" align="middle" fullscreen="" width="1504" height="1504" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/135510/vuori-ponto-shorts-mens" target="_blank" rel="nofollow" data-dimension112="ab7c957c-c96d-11f1-8c2f-551acf235c35" data-action="Deal Block" data-label="Ponto Shorts (Men's)" data-dimension48="Ponto Shorts (Men's)" data-dimension25="$66">Ponto Shorts (Men's): was $84 now $66</a></strong><br />Designed for running or traditional workouts, these men's shorts are super lightweight, quick drying and extra durable. They come in a variety of colors and feature an elastic waistband with a drawstring and two side pockets.<a class="view-deal button" href="https://www.rei.com/product/135510/vuori-ponto-shorts-mens" target="_blank" rel="nofollow" data-dimension112="ab7c957c-c96d-11f1-8c2f-551acf235c35" data-action="Deal Block" data-label="Ponto Shorts (Men's)" data-dimension48="Ponto Shorts (Men's)" data-dimension25="$66">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c95ea-c96d-11f1-88a8-4ba0515079e6" data-action="Deal Block" data-label="Sunday Performance Joggers (Men's)" data-dimension48="Sunday Performance Joggers (Men's)" data-dimension25="$87" href="https://www.rei.com/product/135508/vuori-sunday-performance-joggers-mens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="75meAdFeU6zxP3XWR3ZwdL" name="Vuori joggers" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/75meAdFeU6zxP3XWR3ZwdL-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/135508/vuori-sunday-performance-joggers-mens" target="_blank" rel="nofollow" data-dimension112="ab7c95ea-c96d-11f1-88a8-4ba0515079e6" data-action="Deal Block" data-label="Sunday Performance Joggers (Men's)" data-dimension48="Sunday Performance Joggers (Men's)" data-dimension25="$87">Sunday Performance Joggers (Men's): was $110 now $87</a></strong><br />You'll never want to take these pants off! They feature premium knit fabric that wicks moisture and dries fast. There's also five functional pockets, including 3 with zippers, that will keep valuables secure. They're perfect for any casual occasion and will quickly become your go-to.<a class="view-deal button" href="https://www.rei.com/product/135508/vuori-sunday-performance-joggers-mens" target="_blank" rel="nofollow" data-dimension112="ab7c95ea-c96d-11f1-88a8-4ba0515079e6" data-action="Deal Block" data-label="Sunday Performance Joggers (Men's)" data-dimension48="Sunday Performance Joggers (Men's)" data-dimension25="$87">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c964e-c96d-11f1-be8f-d544e782a7b0" data-action="Deal Block" data-label="Sedona Straight Leg Pants (Women's)" data-dimension48="Sedona Straight Leg Pants (Women's)" data-dimension25="$53" href="https://www.rei.com/product/248919/vuori-sedona-straight-leg-pants-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="5FnZvZECdE34yUWSTyiepZ" name="straight leg pants" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/5FnZvZECdE34yUWSTyiepZ-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/248919/vuori-sedona-straight-leg-pants-womens" target="_blank" rel="nofollow" data-dimension112="ab7c964e-c96d-11f1-be8f-d544e782a7b0" data-action="Deal Block" data-label="Sedona Straight Leg Pants (Women's)" data-dimension48="Sedona Straight Leg Pants (Women's)" data-dimension25="$53">Sedona Straight Leg Pants (Women's): was $108 now $53</a></strong><br />I'm adding this pair of straight leg pants to my cart ASAP! I love everything about them from their relaxed style to their versatility. I can't wait to wear them for travel days, running errands or just hanging out around the house.<a class="view-deal button" href="https://www.rei.com/product/248919/vuori-sedona-straight-leg-pants-womens" target="_blank" rel="nofollow" data-dimension112="ab7c964e-c96d-11f1-be8f-d544e782a7b0" data-action="Deal Block" data-label="Sedona Straight Leg Pants (Women's)" data-dimension48="Sedona Straight Leg Pants (Women's)" data-dimension25="$53">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c96bc-c96d-11f1-b533-617c0b52127a" data-action="Deal Block" data-label="Daydream Crew Top (Women's)" data-dimension48="Daydream Crew Top (Women's)" data-dimension25="$53" href="https://www.rei.com/product/141066/vuori-daydream-crew-top-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="FjY7FhnTftW5pCVDcAcaZa" name="Vuori deal" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/FjY7FhnTftW5pCVDcAcaZa-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/141066/vuori-daydream-crew-top-womens" target="_blank" rel="nofollow" data-dimension112="ab7c96bc-c96d-11f1-b533-617c0b52127a" data-action="Deal Block" data-label="Daydream Crew Top (Women's)" data-dimension48="Daydream Crew Top (Women's)" data-dimension25="$53">Daydream Crew Top (Women's): was $68 now $53</a></strong><br />I have my eye on this Vuori crew top that's made with a high-performance stretch fabric that wicks moisture, dries fast and blocks the sun's harmful rays. It's perfect for workouts, running errands or just hanging out around the house. <a class="view-deal button" href="https://www.rei.com/product/141066/vuori-daydream-crew-top-womens" target="_blank" rel="nofollow" data-dimension112="ab7c96bc-c96d-11f1-b533-617c0b52127a" data-action="Deal Block" data-label="Daydream Crew Top (Women's)" data-dimension48="Daydream Crew Top (Women's)" data-dimension25="$53">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c972a-c96d-11f1-a7a5-3586f5673094" data-action="Deal Block" data-label="AllTheForm Support Tank Top (Women's)" data-dimension48="AllTheForm Support Tank Top (Women's)" data-dimension25="$58" href="https://www.rei.com/product/249019/vuori-alltheform-support-tank-top-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="jNR8qhsVXiAGcNk3HmCoyT" name="tank vuori" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/jNR8qhsVXiAGcNk3HmCoyT-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/249019/vuori-alltheform-support-tank-top-womens" target="_blank" rel="nofollow" data-dimension112="ab7c972a-c96d-11f1-a7a5-3586f5673094" data-action="Deal Block" data-label="AllTheForm Support Tank Top (Women's)" data-dimension48="AllTheForm Support Tank Top (Women's)" data-dimension25="$58">AllTheForm Support Tank Top (Women's): was $74 now $58</a></strong><br />This medium support top with a shelf bra is best suited to studio classes, gym sessions and everyday walking workouts, but it's so comfortable you won't want to wear anything else. Don't miss out on this $16 price cut!<a class="view-deal button" href="https://www.rei.com/product/249019/vuori-alltheform-support-tank-top-womens" target="_blank" rel="nofollow" data-dimension112="ab7c972a-c96d-11f1-a7a5-3586f5673094" data-action="Deal Block" data-label="AllTheForm Support Tank Top (Women's)" data-dimension48="AllTheForm Support Tank Top (Women's)" data-dimension25="$58">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c9806-c96d-11f1-80c7-bd9a60849d6e" data-action="Deal Block" data-label="AllTheFeels Leggings (Women's)" data-dimension48="AllTheFeels Leggings (Women's)" data-dimension25="$65" href="https://www.rei.com/product/228199/vuori-allthefeels-leggings-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2000px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="DxpmvTSCWEk3VveHKETA2U" name="leggings" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/DxpmvTSCWEk3VveHKETA2U-1920-80.jpg" mos="" align="middle" fullscreen="" width="2000" height="2000" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/228199/vuori-allthefeels-leggings-womens" target="_blank" rel="nofollow" data-dimension112="ab7c9806-c96d-11f1-80c7-bd9a60849d6e" data-action="Deal Block" data-label="AllTheFeels Leggings (Women's)" data-dimension48="AllTheFeels Leggings (Women's)" data-dimension25="$65">AllTheFeels Leggings (Women's): was $110 now $65</a></strong><br />Designed for yoga, lounging or anything in  between, these pants feature buttery soft fabric with a cloud-like feel. They're lightweight and stretchy so you can enjoy a full range of motion while sporting them. <a class="view-deal button" href="https://www.rei.com/product/228199/vuori-allthefeels-leggings-womens" target="_blank" rel="nofollow" data-dimension112="ab7c9806-c96d-11f1-80c7-bd9a60849d6e" data-action="Deal Block" data-label="AllTheFeels Leggings (Women's)" data-dimension48="AllTheFeels Leggings (Women's)" data-dimension25="$65">View Deal</a></p></div><div class="product"><a data-dimension112="ab7c9874-c96d-11f1-8d87-7399264b521e" data-action="Deal Block" data-label="Alpine Jacket (Women's)" data-dimension48="Alpine Jacket (Women's)" data-dimension25="$93" href="https://www.rei.com/product/252323/vuori-alpine-jacket-womens" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1803px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="cq7sUCDGx753aFkJ98baq9" name="alpine jacket" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/cq7sUCDGx753aFkJ98baq9-1920-80.jpg" mos="" align="middle" fullscreen="" width="1803" height="1803" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://www.rei.com/product/252323/vuori-alpine-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c9874-c96d-11f1-8d87-7399264b521e" data-action="Deal Block" data-label="Alpine Jacket (Women's)" data-dimension48="Alpine Jacket (Women's)" data-dimension25="$93">Alpine Jacket (Women's): was $188 now $93</a></strong><br />This cute and cozy jacket is 51% off and the perfect layer for fall. Crafted from 100% recycled fleece, the jacket has an oversize fit and zip hand pockets. <a class="view-deal button" href="https://www.rei.com/product/252323/vuori-alpine-jacket-womens" target="_blank" rel="nofollow" data-dimension112="ab7c9874-c96d-11f1-8d87-7399264b521e" data-action="Deal Block" data-label="Alpine Jacket (Women's)" data-dimension48="Alpine Jacket (Women's)" data-dimension25="$93">View Deal</a></p></div><h3 class="article-body__section" id="section-more-deals"><span>More Deals</span></h3><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Running&amp;view_mode=savings_squad&amp;widget_title=Top+Deals+Handpicked+by+Our+Editors&amp;widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&amp;bg_color=transparent" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function getTimeAgo(dateString) {        if (!dateString) return '';        const date = new Date(dateString);        const now = new Date();        const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);        if (diffInSeconds < 60) return 'Just now';        const diffInMinutes = Math.floor(diffInSeconds / 60);        if (diffInMinutes < 60) return `${diffInMinutes} min${diffInMinutes > 1 ? 's' : ''} ago`;        const diffInHours = Math.floor(diffInMinutes / 60);        if (diffInHours < 24) return `${diffInHours} hr${diffInHours > 1 ? 's' : ''} ago`;        const diffInDays = Math.floor(diffInHours / 24);        if (diffInDays < 30) return `${diffInDays} day${diffInDays > 1 ? 's' : ''} ago`;        const diffInMonths = Math.floor(diffInDays / 30);        if (diffInMonths < 12) return `${diffInMonths} mo${diffInMonths > 1 ? 's' : ''} ago`;        const diffInYears = Math.floor(diffInDays / 365);        return `${diffInYears} yr${diffInYears > 1 ? 's' : ''} ago`;      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;      position: relative;      z-index: 20;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      margin: 0 auto;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {      display: grid;      width: 100%;      grid-template-columns: repeat(4, 1fr);      gap: 12px;      margin: 0 auto;      max-width: 800px;    }                 .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;      width: 100%;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      width: 100%;      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }    @container tg-df (max-width: 768px) {      .tg-df-filters-container {      position: relative;      width: 100%;      max-width: 800px;    }    .tg-df-scroll-btn {      display: none;      position: absolute;      top: 50%;      transform: translateY(-50%);      width: 32px;      height: 32px;      background: white;      border: 1px solid var(--tg-df-border);      border-radius: 50%;      align-items: center;      justify-content: center;      cursor: pointer;      z-index: 10;      box-shadow: 0 2px 8px rgba(0,0,0,0.1);      color: var(--tg-df-text-primary);      padding: 0;    }    .tg-df-scroll-btn svg {      width: 16px;      height: 16px;    }    .tg-df-scroll-btn:hover {      background: #f4f4f4;    }    .tg-df-scroll-btn.left {      left: 0px;    }    .tg-df-scroll-btn.right {      right: 0px;    }    @container tg-df (max-width: 768px) {      .tg-df-scroll-btn {        display: flex;        top: 22px; /* vertically center within the 44px high filter buttons */      }    }    .tg-df-filters {        width: 100%;        margin: 0;        margin-bottom: -320px;        padding: 0 16px 320px 16px;        display: flex;        flex-wrap: nowrap;        gap: 8px;        overflow-x: auto;        overflow-y: hidden;        pointer-events: none;        scrollbar-width: none;        -webkit-overflow-scrolling: touch;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }      .tg-df-sort-wrapper {        pointer-events: auto;        flex: 0 0 auto;        width: 175px;        min-width: 175px;      }    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 120px;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 16px 16px 8px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }                  .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;        width: auto;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;      width: 100vw;      max-width: 1200px;      position: relative;      left: 50%;      transform: translateX(-50%);    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 14px;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    .tg-df-grid-wrapper { position: relative; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn {      display: inline-flex;      align-items: center;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.40);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #1f69ff; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #0056e0; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }    .tg-df-savings-squad-header { margin-bottom: 24px; text-align: center; display: none; }    .tg-df-banner-img-desktop { display: block; width: 100%; height: auto; margin-bottom: 32px; }    .tg-df-banner-img-mobile { display: none; width: 100%; height: auto; margin-bottom: 32px; }    @container tg-df (max-width: 600px) {      .tg-df-banner-img-desktop { display: none; }      .tg-df-banner-img-mobile { display: block; }    }    .tg-df-header-title { font-size: 28px; font-weight: 700; color: var(--tg-df-text); margin: 32px 0 12px 0; line-height: 1.3; }    .tg-df-header-subtitle { font-size: 16px; color: var(--tg-df-text-muted); margin: 0 0 32px 0; line-height: 1.5; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3Cdiv class="tg-df-savings-squad-header" id="tg-df-savings-squad-header">      \x3Cpicture>        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/xkh2og7m3d1778189998.png" alt="Deals Banner" class="tg-df-banner-img-desktop" />        \x3Cimg src="https://cdn.mos.cms.futurecdn.net/flexiimages/gmak6rtdf41778245089.png" alt="Deals Banner Mobile" class="tg-df-banner-img-mobile" />      \x3C/picture>      \x3Cdiv class="tg-df-header-text">        \x3Ch2 class="tg-df-header-title" id="tg-df-header-title">Editor's Choice Deals\x3C/h2>        \x3Cp class="tg-df-header-subtitle" id="tg-df-header-subtitle">Discover the best discounts currently available, curated daily by the Tom's Guide Savings Squad.\x3C/p>      \x3C/div>    \x3C/div>    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Televisions" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/wcMxTsHgqu3roMbAx7RLnT-132-100.png" alt="TVs" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">TVs\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Phones" data-pr="over50">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/G3KGaRGzj24F6PUsw4bWpT-132-100.png" alt="Phones" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Phones\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Computing" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/znNvsLzx8NEgNkD9HSFSnT-132-100.png" alt="Computing" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Computing\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Gaming" data-pr="all">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/Pgew8yaRQeZFHqHjTzvBnT-132-100.png" alt="Gaming" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Gaming\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Mattresses" data-pr="over500">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/cW7xsaLyesxkHFVSiC4kmT-132-100.png" alt="Mattresses" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Mattresses\x3C/span>            \x3C/div>                      \x3Cdiv class="tg-df-roundel tg-df-carousel-cat" data-query="Audio" data-pr="over30">              \x3Cdiv class="tg-df-roundel-img-box">                 \x3Cimg src="https://cdn.mos.cms.futurecdn.net/pCvBVHuhaQVjKt3VgCjbqT-132-100.png" alt="Audio" />              \x3C/div>              \x3Cspan class="tg-df-roundel-label">Audio\x3C/span>            \x3C/div>                  \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E      \x3Cdiv class="tg-df-top-bar" id="tg-df-top-bar" style="position: relative; z-index: 100; margin: 0 auto 20px;">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>      \x3C/div>    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">              \x3Cdiv class="tg-df-filters-container" style="position: relative; width: 100%; max-width: 800px; margin: 0 auto;">          \x3Cbutton class="tg-df-scroll-btn left" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: -200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M15 18l-6-6 6-6"/>\x3C/svg>          \x3C/button>          \x3Cbutton class="tg-df-scroll-btn right" style="display: none;" onclick="this.parentElement.querySelector('.tg-df-filters').scrollBy({left: 200, behavior: 'smooth'})">            \x3Csvg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\x3Cpath d="M9 18l6-6-6-6"/>\x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-filters">          \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>          \x3C/div>        \x3C/div>        \x3C/div>      \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();        }        getViewMode() {          console.log("DEBUG getViewMode -> override:", this.viewModeOverride, "editorMode:", this.editorMode);          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          console.log("[DEBUG] applyLayoutMode CALLED! mode=", mode);          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          const showHeaderDetails = params.get('show_header_details') !== 'false';          const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          const topBarDiv = this.root.querySelector('#tg-df-top-bar');          const headerElement = this.root.querySelector('#tg-df-savings-squad-header');          if (headerElement) {             headerElement.style.display = (mode === 'savings_squad' && showHeaderDetails) ? 'block' : 'none';          }          if (mode === 'carousel') {             this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (topBarDiv) topBarDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.add('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (topBarDiv) topBarDiv.style.display = 'block';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!this.viewModeOverride && initialViewMode) {            this.viewModeOverride = initialViewMode;          }          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Gaming laptops';          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (this.viewModeSelect && params.has('view_mode')) {            this.viewModeSelect.value = params.get('view_mode');          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'date_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }          const headerTitleEl = this.root.querySelector('#tg-df-header-title');          const headerSubtitleEl = this.root.querySelector('#tg-df-header-subtitle');          if (params.has('widget_title') && headerTitleEl) {             headerTitleEl.textContent = params.get('widget_title');          }          if (params.has('widget_subtitle') && headerSubtitleEl) {             headerSubtitleEl.textContent = params.get('widget_subtitle');          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            if (this.getViewMode() === 'savings_squad') {              this.searchInput.value = '';            } else {              this.searchInput.value = this.currentQuery;            }          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'date_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const handleFiltersScroll = () => {            const filters = this.root.querySelector('.tg-df-filters');            const leftBtn = this.root.querySelector('.tg-df-scroll-btn.left');            const rightBtn = this.root.querySelector('.tg-df-scroll-btn.right');            if (filters && leftBtn && rightBtn) {              const { scrollLeft, scrollWidth, clientWidth } = filters;              leftBtn.style.display = scrollLeft > 0 ? 'flex' : 'none';              rightBtn.style.display = Math.ceil(scrollLeft + clientWidth) < scrollWidth - 5 ? 'flex' : 'none';            }          };          const filters = this.root.querySelector('.tg-df-filters');          if (filters) {            filters.addEventListener('scroll', handleFiltersScroll);            window.addEventListener('resize', handleFiltersScroll);            setTimeout(handleFiltersScroll, 100);                        // Also call after rendering dropdowns            const origRenderCategories = this.renderCategories;            if (origRenderCategories) {               this.renderCategories = (...args) => {                 origRenderCategories.apply(this, args);                 setTimeout(handleFiltersScroll, 50);               };            }          }                const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          const showAutocomplete = () => {             if (this.getViewMode() !== 'savings_squad' || !this.autocompleteDropdown || !this.airedaleTags) return;                          let terms = this.airedaleTags;             if (this.airedaleBrands) {                terms = terms.concat(this.airedaleBrands.map(b => b.formatted_value));             }             terms = [...new Set(terms)];                          const query = this.searchInput.value.trim();             let matches = [];             if (query.length > 0) {                 matches = terms.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase());             } else {                 matches = terms;             }                          if (matches.length > 0) {                 this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                 this.autocompleteDropdown.classList.add('active');             } else {                 this.autocompleteDropdown.classList.remove('active');             }          };          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('focus', showAutocomplete);            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              showAutocomplete();              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  if (this.getViewMode() === 'savings_squad') {                    this.activeDealTag = null;                    this.currentQuery = '';                    if (this.categoryFilter) this.categoryFilter.value = 'all';                    this.fetchDeals('');                  } else {                    this.deals = [];                    this.render();                  }                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                                let isTag = false;                if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;                if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;                this.activeDealTag = isTag ? query : null;                                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   if (query.length === 0 && this.getViewMode() === 'savings_squad') {                       if (this.categoryFilter) this.categoryFilter.value = 'all';                   }                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   if (this.categoryFilter && this.airedaleTags.includes(tag)) {                       this.categoryFilter.value = tag;                   }                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                            let isTag = false;              if (this.airedaleTags && this.airedaleTags.includes(query)) isTag = true;              if (this.airedaleBrands && this.airedaleBrands.some(b => b.formatted_value === query)) isTag = true;              this.activeDealTag = isTag ? query : null;                            this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 if (query.length === 0 && this.getViewMode() === 'savings_squad') {                     if (this.categoryFilter) this.categoryFilter.value = 'all';                 }                 this.fetchDeals(query);              }            });          }          if(this.sortSelect && this.sortSelect.querySelector('option[value="date_desc"]') === null) {              const option = document.createElement('option');              option.value = "date_desc";              option.text = "Newest First";              this.sortSelect.insertBefore(option, this.sortSelect.firstChild);          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               if (val) {                 this.currentQuery = val;               } else {                 if (this.searchInput && this.currentQuery === document.querySelector('#tg-df-brand-trigger')?.getAttribute('data-active-brand')) {                     // don't clear current query if a brand is selected                 } else if (this.searchInput) {                     this.currentQuery = '';                     this.searchInput.value = '';                 }               }               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = 'date_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }        async fetchDeals(query) {          this.showLoading();          this.deals = [];          this.displayLimit = this.getRowsLimit();                    try {            console.log("getViewMode returns:", this.getViewMode());            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad();            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query);               } else {                 await this.fetchHawkDeals(query);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const siteParam = this.website || 'tomsguide';            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=${siteParam}&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (!this.activeDealTag && this.currentQuery) {             const tagMatch = this.airedaleTags.find(t => t.toLowerCase() === this.currentQuery.toLowerCase());             if (tagMatch) {                this.activeDealTag = tagMatch;             }          }          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const siteParam = this.website || 'tomsguide';             const url = `https://airedale.futurecdn.net/feeds/feed_1781000519267.json?site=${siteParam}&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let seenUrls = new Set();                    let overallBrandsCounts = {};                    // First pass: extract ALL brands from topArticles so the dropdown has all options          topArticles.forEach((article) => {             if (!article.articlepage) return;             let pageData = [];             try { pageData = JSON.parse(article.articlepage[0]); } catch(e){ console.warn(e); }             const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');             savingsSquad.forEach((block) => {                const data = block.data || {};                if (data.brand) {                   const cleanBrand = data.brand.replace(/^\d+\.\s*/, '').trim();                   overallBrandsCounts[cleanBrand] = (overallBrandsCounts[cleanBrand] || 0) + 1;                }             });          });          targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                if (externalUrl) {                   if (seenUrls.has(externalUrl)) return;                  seenUrls.add(externalUrl);                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || '',                   authorName: article.articleauthortext ? article.articleauthortext[0] : (article.articleauthor ? article.articleauthor[0] : ''),                   authorRole: article.articleauthorrole ? article.articleauthorrole[0] : '',                   authorImage: article.articleauthormedia ? article.articleauthormedia[0] : '',                   documentUrl: article.documenturl ? article.documenturl[0] : '',                   modifiedDate: article.contentmodifieddate || article.modifieddate || ''                });             });          });                    const airedaleBrandsList = Object.keys(overallBrandsCounts).map(b => ({              formatted_value: b,              count: overallBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : 'date_desc';          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                ${_div}              ${_div}              \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin:0; border-radius:0;">${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)}${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = 'View Deal';              if (isSavingsSquadMode) {                priceGroupHtml = ``;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = isSavingsSquadMode ? `` : `                \x3Cdiv class="tg-df-card-price-group">                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                          \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                          \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                            var c = this.parentNode;                            if (this.dataset.expanded === 'true') {                              var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                              if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                              pd.style.display = '-webkit-box';                              pd.style.webkitLineClamp = '3';                              this.textContent = 'READ MORE';                              this.style.position = 'absolute';                              this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                              this.style.paddingLeft = '16px';                              this.dataset.expanded = 'false';                            } else {                              var pd = this.previousElementSibling;                              pd.style.display = 'inline';                              pd.style.webkitLineClamp = 'unset';                              this.textContent = 'READ LESS';                              this.style.position = 'static';                              this.style.background = 'transparent';                              this.style.paddingLeft = '4px';                              this.dataset.expanded = 'true';                              pd.appendChild(this);                            }                          ">READ MORE${_button}                        \x3C/div>` : ''}                      ${_div}                    ${_div}                    ${deal.authorName ? `                      \x3Cdiv class="tg-df-author-line-mobile" style="padding: 0 0 12px 0; background: transparent;">                         \x3Cdiv style="display: flex; align-items: center; gap: 12px;">                            ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="40" height="40" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 40px; min-height: 40px;">` : ''}                            \x3Cdiv style="display: flex; flex-direction: column;">                               \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">\x3Cspan style="color: #FF6600;">${this.escapeHTML(deal.merchant)}${_span} deal recommended by:${_div}                               \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.3;">                                  \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                  ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                  ${deal.modifiedDate ? `\x3Cdiv style="color: var(--tg-df-text-muted); margin-top: 2px;">${getTimeAgo(deal.modifiedDate)}${_div}` : ''}                               ${_div}                            ${_div}                         ${_div}                      ${_div}                    ` : ''}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>View Deal${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                  \x3Cdiv class="tg-df-card-merchant-wrapper" style="position: absolute; bottom: 0; right: 0; background: transparent; padding: 8px 12px; z-index: 10;">                     \x3Cspan class="tg-df-card-merchant-pill" style="text-align: right; margin-bottom: 0;" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cdiv class="tg-df-card-desc-container" style="margin-bottom: 12px; position: relative;">                    \x3Cp class="tg-df-card-desc-content" style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 0; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;">${this.escapeHTML(deal.description)}${_p}                    \x3Cbutton type="button" class="tg-df-card-desc-btn" style="display: none; appearance: none; border: none; color: #000000; font-size: 11px; font-weight: 700; text-transform: uppercase; cursor: pointer; font-family: inherit; position: absolute; bottom: 2px; right: 0; background: linear-gradient(to right, transparent, #fff 20%, #fff); padding: 0 0 0 16px;" onclick="                      var c = this.parentNode;                      if (this.dataset.expanded === 'true') {                        var pd = (c.tagName === 'P') ? c : this.previousElementSibling;                        if (c.tagName === 'P') { c.parentNode.appendChild(this); pd = c; }                        pd.style.display = '-webkit-box';                        pd.style.webkitLineClamp = '3';                        this.textContent = 'READ MORE';                        this.style.position = 'absolute';                        this.style.background = 'linear-gradient(to right, transparent, #fff 20%, #fff)';                        this.style.paddingLeft = '16px';                        this.dataset.expanded = 'false';                      } else {                        var pd = this.previousElementSibling;                        pd.style.display = 'inline';                        pd.style.webkitLineClamp = 'unset';                        this.textContent = 'READ LESS';                        this.style.position = 'static';                        this.style.background = 'transparent';                        this.style.paddingLeft = '4px';                        this.dataset.expanded = 'true';                        pd.appendChild(this);                      }                    ">READ MORE${_button}                  \x3C/div>` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${deal.authorName ? `                    \x3Cdiv class="tg-df-author-line-desktop" style="padding: 0 0 ${isSavingsSquadMode ? 0 : 12}px 0;">                       \x3Cdiv style="display: flex; align-items: center; gap: 10px;">                          ${deal.authorImage ? `\x3Cimg src="${this.escapeHTML(deal.authorImage)}" alt="${this.escapeHTML(deal.authorName)}" class="tg-df-author-img" width="36" height="36" style="border-radius: 50%; object-fit: cover; flex-shrink: 0; aspect-ratio: 1 / 1; min-width: 36px; min-height: 36px;">` : ''}                          \x3Cdiv style="display: flex; flex-direction: column;">                             \x3Cdiv style="font-size: 10px; color: var(--tg-df-text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px; font-weight: 600;">Recommended by:${_div}                             \x3Cdiv style="font-size: 11px; color: var(--tg-df-text); line-height: 1.2;">                                \x3Cstrong>\x3Ca href="https://www.tomsguide.com/${this.escapeHTML(deal.documentUrl || '').replace(/^\/+/, '')}" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit; border-bottom: 1px dotted var(--tg-df-text-muted);">${this.escapeHTML(deal.authorName)}${_a}${_strong}                                ${deal.authorRole && !['null', 'nul', 'undefined'].includes(String(deal.authorRole).toLowerCase()) ? ` • ${this.escapeHTML(deal.authorRole)}` : ''}                                ${deal.modifiedDate ? `\x3Cspan style="color: var(--tg-df-text-muted);"> • ${getTimeAgo(deal.modifiedDate)}${_span}` : ''}                             ${_div}                          ${_div}                       ${_div}                    ${_div}                    ` : ''}                    ${priceGroupHtml}                  ${_div}                ${_div}                \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta" style="text-decoration: none; border-radius: 0;">${ctaText}${_a}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit) {            dealsHtml += `              \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer;">Load More${_button}              ${_div}            `;          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }          setTimeout(() => {            const contents = this.root.querySelectorAll('.tg-df-card-desc-content');            contents.forEach(p => {              if (p.scrollHeight > p.clientHeight || p.scrollHeight > 60) {                if (p.nextElementSibling) {                  p.nextElementSibling.style.display = 'block';                }              }            });                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');            document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));          }, 50);          const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              this.displayLimit += this.getRowsLimit();              this.render();            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I’ve been testing these hiking boots, and they’re the answer for staying comfortable on casual walks ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Not every pair of hiking boots has to be able to take you up the tallest mountain. For the last year, I’ve been looking for the <a href="https://www.tomsguide.com/best-picks/best-hiking-boots">best hiking boots</a> for casual hikes and weekend wanders through the woods. And after a lot of searching, I think I’ve found them.</p><p>The Scarpa Cyrus 2 Mid GTX boots don’t claim to be the most heavy-duty boots out there, but they are totally waterproof, have great traction and a durable build. What’s more, these boots are comfortable straight out of the box — no break-in period. </p><p>The minimal insole cushioning may put off those with sensitive soles, and the fit is pretty snug, but even with that, I’ve been loving my walks with these boots. To find out more, keep reading this full Scarpa Cyrus 2 Mid GTX review. </p><h2 class="article-body__section" id="section-scarpa-cyrus-2-mid-gtx-review-specs"><span>Scarpa Cyrus 2 Mid GTX review: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.sportsshoes.com/product/sca509/scarpa-cyrus-2-mid-gore-tex-women's-walking-boots---aw26" target="_blank" rel="nofollow">$240</a> / <a href="https://www.scarpa.co.uk/products/cyrus-2-mid-gtx-wmn-womens-walking-boots" target="_blank" rel="nofollow">£195</a></p></td></tr><tr><td class="firstcol " ><p><strong>Size availability</strong></p></td><td  ><p>U.S. Sizes 6 - 10 with half sizes </p><p>U.K. Sizes 4 - 8 with half sizes</p></td></tr><tr><td class="firstcol " ><p><strong>Weight (per boot)</strong></p></td><td  ><p>12.7 ounces</p></td></tr><tr><td class="firstcol " ><p><strong>Colors</strong></p></td><td  ><p>Brown</p></td></tr><tr><td class="firstcol " ><p><strong>Materials</strong></p></td><td  ><p>Nubuck leather</p></td></tr><tr><td class="firstcol " ><p><strong>Waterproofing</strong></p></td><td  ><p>Gore-Tex</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-scarpa-cyrus-2-mid-gtx-review-price-availability"><span>Scarpa Cyrus 2 Mid GTX review: Price &amp; availability</span></h2><p>You can purchase the Scarpa Cyrus 2 Mid GTX boots for <a href="https://www.sportsshoes.com/product/sca509/scarpa-cyrus-2-mid-gore-tex-women's-walking-boots---aw26" target="_blank" rel="nofollow">$240 from third-party retailers such as the Sports boots</a> online store, since unfortunately Scarpa does not sell this specific boot directly in the U.S. But if you’re in the U.K., you can buy the boots for <a href="https://www.scarpa.co.uk/products/cyrus-2-mid-gtx-wmn-womens-walking-boots" target="_blank" rel="nofollow">£195 directly from the Scarpa</a> online store.  </p><p>I tested the women’s version of the boots, and they also come in a low-cut version. The women’s version of the mid boot is available in U.S. Sizes 6 to 10 with half sizes and U.K. Sizes 4 to 8 with half sizes. I’m usually a U.K. size 5, but I had to size up to a 5 and a half. You can also buy a men’s version, which is slightly different as they have a much wider fit, but unfortunately, I couldn’t see any availability for the men’s shoe in the U.S.</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="SxRQJR2bsH8fwyftxd6dTA" name="Scarpa Cyrus 2 Mid GTX" alt="Scarpa Cyrus 2 Mid GTX brown hiking boots" src="https://cdn.mos.cms.futurecdn.net/SxRQJR2bsH8fwyftxd6dTA-1920-80.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>In looks, these boots remind me of the <a href="https://www.tomsguide.com/wellness/fitness/keen-targhee-iv-review">Keen Targhee IV</a>, which are my go-to for taking on the outdoors. The Keens cost $169 / £155 and are a better choice if you have wider feet and require a roomy toe box. </p><p>If you want a boot with a lot more traction, I’d recommend looking at the <a href="http://review">Keen Targhee Apex Mid</a> hiking boots. These boots cost $190 / £150 but are better if you need a lot of traction and secure ankle support for a tricky trail. </p><h2 class="article-body__section" id="section-scarpa-cyrus-2-mid-gtx-review-design-build"><span>Scarpa Cyrus 2 Mid GTX review: Design &amp; build</span></h2><p>The Scarpa Cyrus 2 Mid GTX are a good-looking boot. They’re exactly what comes to mind when I think of a hiking boot, and I felt ready for the elements when I wore them. The brown color is very pretty and actually does a good job of disguising any mud that gets onto the boot.</p><p>Each boot weighs 12.7 ounces, and they’re very easy to walk in, not making me feel like I’m lugging extra weight on my feet. I could feel they were lighter than the Keen Targhee IV that I usually hike in, and I could walk a lot further before my legs started to ache. </p><h3 id="upper">Upper</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="4dUgCJuEcq9c6x4ruzEmvA" name="Scarpa Cyrus 2 Mid GTX" alt="Scarpa Cyrus 2 Mid GTX brown hiking boots" src="https://cdn.mos.cms.futurecdn.net/4dUgCJuEcq9c6x4ruzEmvA-1920-80.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 upper of the Cyrus 2 Mid GTX is made from Nubuck leather, which feels strong, but still moves with the contours and bend of my foot and ankle. It looks similar to the leather variant of the <a href="https://www.tomsguide.com/wellness/fitness/merrell-moab-speed-2-review">Merrell Moab Speed 2</a>. The Cyrus has a GORE-TEX membrane, making the boots completely waterproof — and hiking where I’m from, I was very grateful for this. </p><p>There’s a lot of padding around the ankle, which is great for me. As anyone who knows me will tell you, I’m <em>very</em> clumsy, so having a bit of extra support to avoid rolled ankles is always good. </p><h3 id="insole">Insole</h3><p>The insole of the Scarpa boots doesn’t have a whole lot of cushioning. However, I don’t think this made me like the boots any less. It made the fit of the boots feel more relaxed, suiting them to casual walks and hikes, rather than for challenging mountaineering. </p><h3 id="outsole">Outsole</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="e7YuBMzLsYETVh8bBS7onA" name="Scarpa Cyrus 2 Mid GTX" alt="Scarpa Cyrus 2 Mid GTX brown hiking boots" src="https://cdn.mos.cms.futurecdn.net/e7YuBMzLsYETVh8bBS7onA-1920-80.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 boots use a Scarpa Presa outsole, which is made of a rubber compound designed to deal with a range of outdoor terrain. It works well for all terrain I tested on, which I’ll talk about more later. They have lugs that gave me stability on both wet and dry ground. These boots have great traction, and the sole isn’t too thick, so there’s a good amount of flex. </p><h2 class="article-body__section" id="section-scarpa-cyrus-2-mid-gtx-review-break-in-comfort"><span>Scarpa Cyrus 2 Mid GTX review: Break-in &amp; comfort</span></h2><p>The Scarpa Cyrus 2 Mid GTX hiking boots are perfect if you don’t have time to break in your boots before a big adventure — they’re good to go straight out of the box. The first walk I took in these boots was a 5km round trail with varying terrain and incline, and because the boots felt so stable, I didn’t have any issues with rubbing, meaning no hot spots that can cause blisters. </p><h2 id="comfort">Comfort</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="NbxvvxakwnousL5Bvcvmy9" name="Scarpa Cyrus 2 Mid GTX" alt="Scarpa Cyrus 2 Mid GTX brown hiking boots" src="https://cdn.mos.cms.futurecdn.net/NbxvvxakwnousL5Bvcvmy9-1920-80.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 boots are extremely comfortable to wear, particularly due to the flex of the outsole that makes each step feel completely natural. The padding on the inside of the upper of the boots made my feet feel secure and supported me whenever there was a bend in my foot. </p><p>Thankfully, these boots are very breathable and everything still felt comfortable when I worked up a sweat. There was enough room in the toe box for me, even when wearing thick socks. I do, however, have narrow feet, so if you usually need a wide fit, I’d recommend the Keen Targhee IV instead for their spacious toe box. </p><p>As I mentioned earlier, there’s not a lot of cushioning in these boots. When I was making my way across rough terrain like rocks embedded in clay, my foot was wrapping around the uneven ground, but I enjoyed this sensation — it made me feel more connected to the landscape and helped me find my footing a lot quicker. I’m pretty sure that if I were blindfolded and you gave me a piece of paper and a pen, I could draw you a picture of the rock from what I felt beneath the soles. </p><h2 class="article-body__section" id="section-scarpa-cyrus-2-mid-gtx-review-performance"><span>Scarpa Cyrus 2 Mid GTX review: Performance</span></h2><p>I like these boots. I like them <em>a lot</em>. They’re comfy, solid, and reliable — what more could you want? They’re best for short hikes with varied terrain, as I found them great across clay, mud, gravel and uneven rocks. Because of the minimal cushioning, I wouldn’t recommend them for weekend-long hikes — but not every boot has to take you through an entire expedition. </p><h2 id="grip">Grip</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="SNsaqFEMPkBwnS9ikNeQ4R" name="Scarpa Cyrus 2 Mid GTX" alt="Scarpa Cyrus 2 Mid GTX brown hiking boots" src="https://cdn.mos.cms.futurecdn.net/SNsaqFEMPkBwnS9ikNeQ4R-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The boots have great grip! Despite my clumsy disposition, I didn’t fall over once. I made my way through mud, sand and over rocks and felt very stable. The legs dug into the ground very well but didn’t hold on to any debris. I tested these boots during fall, and as the weather got wetter where I live, I didn’t have any issues on the slippery ground. </p><h2 id="support">Support</h2><p>Despite the lack of cushioning I mentioned, my feet felt supported. I have high arches and didn’t experience any aches, and I felt my posture was well supported too. Your posture while walking is directly impacted by your footwear, so I’m happy with the results I got. </p><p>The ankle support was impressive, and even when I felt my balance wavering on uneven ground, I knew I had all the support I needed to keep me upright. </p><h2 id="flex">Flex</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4L9sSn9P7qHP2hKYx8sXzQ" name="Scarpa Cyrus 2 Mid GTX" alt="Scarpa Cyrus 2 Mid GTX brown hiking boots" src="https://cdn.mos.cms.futurecdn.net/4L9sSn9P7qHP2hKYx8sXzQ-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Since this is a thinner sole, there’s plenty of flex. The boots were bending with the movement of my feet, and I enjoyed how this made my strides feel natural and unrestricted. </p><p>Flex isn’t always a great thing in walking boots, and some stiffness can offer stability. However, since these boots are designed for shorter hikes and casual walks, it’s good to have some natural movement in your feet. </p><h2 id="waterproofing">Waterproofing</h2><p>Boy, was I thankful for the waterproofing on the Scarpa Cyrus 2 Mid GTX boots. Whilst on a long walk, I found myself at the beach once I emerged from the trees. What a lovely sight, but to get down onto the sand I had to cross a small inlet. That was no big deal for these boots. I was in water just up to the laces, and my feet stayed completely dry. </p><h2 class="article-body__section" id="section-scarpa-cyrus-2-mid-gtx-review-maintenance"><span>Scarpa Cyrus 2 Mid GTX review: Maintenance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="CBGawmVYy5rFuuEqwNKBmA" name="Scarpa Cyrus 2 Mid GTX" alt="Scarpa Cyrus 2 Mid GTX brown hiking boots" src="https://cdn.mos.cms.futurecdn.net/CBGawmVYy5rFuuEqwNKBmA-1920-80.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 Scarpa Cyrus 2 Mid GTX hiking boots are easy to maintain, just like any pair of hiking boots. Since the upper is made from Nubuck leather, you should ensure they’re completely dry before storing them away. I brushed the dirt off my boots once dry, and they looked as good as new. </p><h2 class="article-body__section" id="section-scarpa-cyrus-2-mid-gtx-review-verdict"><span>Scarpa Cyrus 2 Mid GTX review: Verdict</span></h2><p>The Scarpas have good waterproofing, keep my feet dry even in the sea, have a durable build with a Nubuck leather upper, and are comfortable straight out of the box. The boots are lightweight and very flexible, making walking feel very natural. The traction and support also made the journey in these boots very relaxing, knowing I was stable with every step. </p><p>That said, they’re not totally perfect. The cushioning of the insole is minimal, and while this didn’t impact my experience, those with sensitive soles may find them a little uncomfortable. The fit is also a little snug. Sizing up should solve this, but those with wider feet may want to look elsewhere. </p><p>Nevertheless, the Scarpa Cyrus 2 Mid GTX hiking boots are now a firm favorite of mine. I’ve always wanted a pair of boots that I can rely on when the walk requires more than a regular sneaker but doesn’t need mountaineering boots — and now I have them. </p> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/fitness/scarpa-cyrus-2-mid-gtx-review</link>
                                                                            <description>
                            <![CDATA[ The Scarpa Cyrus 2 Mid GTX will have you feeling comfortable and supported on every walk; they’ve become my new go-to pair of boots. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">rxTqiHzVoMY9mzfDS3HFNh</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/K2YwNrbkj5Dzah3JH6QcFA-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 16 Oct 2026 10:24:17 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Fitness]]></category>
                                                    <category><![CDATA[Wellness]]></category>
                                                                                                <author><![CDATA[ ashley.thieme@futurenet.com (Ashley Thieme) ]]></author>                    <dc:creator><![CDATA[ Ashley Thieme ]]></dc:creator>                                                                                    <dc:source><![CDATA[ https://cdn.mos.cms.futurecdn.net/3AWovHjApwuNrSGRS6WBcL-320-70.jpg ]]></dc:source>
                                                                <dc:description><![CDATA[ &lt;p&gt;Ashley Thieme is a staff writer on the Reviews team at Tom’s Guide where she tests out the latest tech so you can know what’s going to be worth your time and money. She has a master’s degree in Magazine Journalism and a bachelor’s degree in Journalism, Media and Sociology from Cardiff University. She has bylines in titles including Women’s Health UK, sharing the latest health and wellness news stories, and Virgin Radio UK, providing the latest entertainment news and working on celebrity interviews. She has experience reporting on a variety of topics including music, literature, motorsport, entertainment and health. In previously published work, she has reviewed live music events, books, and wellness products. She values the importance of tech enhancing your life rather than taking over, and as a music fanatic, she is always looking for the best way to listen to new music releases. Discovering the top audio equipment that enhances sound quality and provides optimum comfort is what Ashley does best. In her spare time, Ashley enjoys hitting her reading goals on Goodreads by getting into the latest novels with a cup of tea as well as getting out in the Welsh mountains for a good hike on the weekend.&lt;/p&gt; ]]></dc:description>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/K2YwNrbkj5Dzah3JH6QcFA-1920-80.jpg">
                                                            <media:credit><![CDATA[Tom&amp;#39;s Guide]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Scarpa Cyrus 2 Mid GTX brown hiking boots]]></media:description>                                                            <media:text><![CDATA[Scarpa Cyrus 2 Mid GTX brown hiking boots]]></media:text>
                                <media:title type="plain"><![CDATA[Scarpa Cyrus 2 Mid GTX brown hiking boots]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/K2YwNrbkj5Dzah3JH6QcFA-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Not every pair of hiking boots has to be able to take you up the tallest mountain. For the last year, I’ve been looking for the <a href="https://www.tomsguide.com/best-picks/best-hiking-boots">best hiking boots</a> for casual hikes and weekend wanders through the woods. And after a lot of searching, I think I’ve found them.</p><p>The Scarpa Cyrus 2 Mid GTX boots don’t claim to be the most heavy-duty boots out there, but they are totally waterproof, have great traction and a durable build. What’s more, these boots are comfortable straight out of the box — no break-in period. </p><p>The minimal insole cushioning may put off those with sensitive soles, and the fit is pretty snug, but even with that, I’ve been loving my walks with these boots. To find out more, keep reading this full Scarpa Cyrus 2 Mid GTX review. </p><h2 class="article-body__section" id="section-scarpa-cyrus-2-mid-gtx-review-specs"><span>Scarpa Cyrus 2 Mid GTX review: Specs</span></h2><div ><table><tbody><tr><td class="firstcol " ><p><strong>Price</strong></p></td><td  ><p><a href="https://www.sportsshoes.com/product/sca509/scarpa-cyrus-2-mid-gore-tex-women's-walking-boots---aw26" target="_blank" rel="nofollow">$240</a> / <a href="https://www.scarpa.co.uk/products/cyrus-2-mid-gtx-wmn-womens-walking-boots" target="_blank" rel="nofollow">£195</a></p></td></tr><tr><td class="firstcol " ><p><strong>Size availability</strong></p></td><td  ><p>U.S. Sizes 6 - 10 with half sizes </p><p>U.K. Sizes 4 - 8 with half sizes</p></td></tr><tr><td class="firstcol " ><p><strong>Weight (per boot)</strong></p></td><td  ><p>12.7 ounces</p></td></tr><tr><td class="firstcol " ><p><strong>Colors</strong></p></td><td  ><p>Brown</p></td></tr><tr><td class="firstcol " ><p><strong>Materials</strong></p></td><td  ><p>Nubuck leather</p></td></tr><tr><td class="firstcol " ><p><strong>Waterproofing</strong></p></td><td  ><p>Gore-Tex</p></td></tr></tbody></table></div><h2 class="article-body__section" id="section-scarpa-cyrus-2-mid-gtx-review-price-availability"><span>Scarpa Cyrus 2 Mid GTX review: Price &amp; availability</span></h2><p>You can purchase the Scarpa Cyrus 2 Mid GTX boots for <a href="https://www.sportsshoes.com/product/sca509/scarpa-cyrus-2-mid-gore-tex-women's-walking-boots---aw26" target="_blank" rel="nofollow">$240 from third-party retailers such as the Sports boots</a> online store, since unfortunately Scarpa does not sell this specific boot directly in the U.S. But if you’re in the U.K., you can buy the boots for <a href="https://www.scarpa.co.uk/products/cyrus-2-mid-gtx-wmn-womens-walking-boots" target="_blank" rel="nofollow">£195 directly from the Scarpa</a> online store.  </p><p>I tested the women’s version of the boots, and they also come in a low-cut version. The women’s version of the mid boot is available in U.S. Sizes 6 to 10 with half sizes and U.K. Sizes 4 to 8 with half sizes. I’m usually a U.K. size 5, but I had to size up to a 5 and a half. You can also buy a men’s version, which is slightly different as they have a much wider fit, but unfortunately, I couldn’t see any availability for the men’s shoe in the U.S.</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="SxRQJR2bsH8fwyftxd6dTA" name="Scarpa Cyrus 2 Mid GTX" alt="Scarpa Cyrus 2 Mid GTX brown hiking boots" src="https://cdn.mos.cms.futurecdn.net/SxRQJR2bsH8fwyftxd6dTA-1920-80.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>In looks, these boots remind me of the <a href="https://www.tomsguide.com/wellness/fitness/keen-targhee-iv-review">Keen Targhee IV</a>, which are my go-to for taking on the outdoors. The Keens cost $169 / £155 and are a better choice if you have wider feet and require a roomy toe box. </p><p>If you want a boot with a lot more traction, I’d recommend looking at the <a href="http://review">Keen Targhee Apex Mid</a> hiking boots. These boots cost $190 / £150 but are better if you need a lot of traction and secure ankle support for a tricky trail. </p><h2 class="article-body__section" id="section-scarpa-cyrus-2-mid-gtx-review-design-build"><span>Scarpa Cyrus 2 Mid GTX review: Design &amp; build</span></h2><p>The Scarpa Cyrus 2 Mid GTX are a good-looking boot. They’re exactly what comes to mind when I think of a hiking boot, and I felt ready for the elements when I wore them. The brown color is very pretty and actually does a good job of disguising any mud that gets onto the boot.</p><p>Each boot weighs 12.7 ounces, and they’re very easy to walk in, not making me feel like I’m lugging extra weight on my feet. I could feel they were lighter than the Keen Targhee IV that I usually hike in, and I could walk a lot further before my legs started to ache. </p><h3 id="upper">Upper</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="4dUgCJuEcq9c6x4ruzEmvA" name="Scarpa Cyrus 2 Mid GTX" alt="Scarpa Cyrus 2 Mid GTX brown hiking boots" src="https://cdn.mos.cms.futurecdn.net/4dUgCJuEcq9c6x4ruzEmvA-1920-80.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 upper of the Cyrus 2 Mid GTX is made from Nubuck leather, which feels strong, but still moves with the contours and bend of my foot and ankle. It looks similar to the leather variant of the <a href="https://www.tomsguide.com/wellness/fitness/merrell-moab-speed-2-review">Merrell Moab Speed 2</a>. The Cyrus has a GORE-TEX membrane, making the boots completely waterproof — and hiking where I’m from, I was very grateful for this. </p><p>There’s a lot of padding around the ankle, which is great for me. As anyone who knows me will tell you, I’m <em>very</em> clumsy, so having a bit of extra support to avoid rolled ankles is always good. </p><h3 id="insole">Insole</h3><p>The insole of the Scarpa boots doesn’t have a whole lot of cushioning. However, I don’t think this made me like the boots any less. It made the fit of the boots feel more relaxed, suiting them to casual walks and hikes, rather than for challenging mountaineering. </p><h3 id="outsole">Outsole</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="e7YuBMzLsYETVh8bBS7onA" name="Scarpa Cyrus 2 Mid GTX" alt="Scarpa Cyrus 2 Mid GTX brown hiking boots" src="https://cdn.mos.cms.futurecdn.net/e7YuBMzLsYETVh8bBS7onA-1920-80.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 boots use a Scarpa Presa outsole, which is made of a rubber compound designed to deal with a range of outdoor terrain. It works well for all terrain I tested on, which I’ll talk about more later. They have lugs that gave me stability on both wet and dry ground. These boots have great traction, and the sole isn’t too thick, so there’s a good amount of flex. </p><h2 class="article-body__section" id="section-scarpa-cyrus-2-mid-gtx-review-break-in-comfort"><span>Scarpa Cyrus 2 Mid GTX review: Break-in &amp; comfort</span></h2><p>The Scarpa Cyrus 2 Mid GTX hiking boots are perfect if you don’t have time to break in your boots before a big adventure — they’re good to go straight out of the box. The first walk I took in these boots was a 5km round trail with varying terrain and incline, and because the boots felt so stable, I didn’t have any issues with rubbing, meaning no hot spots that can cause blisters. </p><h2 id="comfort">Comfort</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="NbxvvxakwnousL5Bvcvmy9" name="Scarpa Cyrus 2 Mid GTX" alt="Scarpa Cyrus 2 Mid GTX brown hiking boots" src="https://cdn.mos.cms.futurecdn.net/NbxvvxakwnousL5Bvcvmy9-1920-80.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 boots are extremely comfortable to wear, particularly due to the flex of the outsole that makes each step feel completely natural. The padding on the inside of the upper of the boots made my feet feel secure and supported me whenever there was a bend in my foot. </p><p>Thankfully, these boots are very breathable and everything still felt comfortable when I worked up a sweat. There was enough room in the toe box for me, even when wearing thick socks. I do, however, have narrow feet, so if you usually need a wide fit, I’d recommend the Keen Targhee IV instead for their spacious toe box. </p><p>As I mentioned earlier, there’s not a lot of cushioning in these boots. When I was making my way across rough terrain like rocks embedded in clay, my foot was wrapping around the uneven ground, but I enjoyed this sensation — it made me feel more connected to the landscape and helped me find my footing a lot quicker. I’m pretty sure that if I were blindfolded and you gave me a piece of paper and a pen, I could draw you a picture of the rock from what I felt beneath the soles. </p><h2 class="article-body__section" id="section-scarpa-cyrus-2-mid-gtx-review-performance"><span>Scarpa Cyrus 2 Mid GTX review: Performance</span></h2><p>I like these boots. I like them <em>a lot</em>. They’re comfy, solid, and reliable — what more could you want? They’re best for short hikes with varied terrain, as I found them great across clay, mud, gravel and uneven rocks. Because of the minimal cushioning, I wouldn’t recommend them for weekend-long hikes — but not every boot has to take you through an entire expedition. </p><h2 id="grip">Grip</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="SNsaqFEMPkBwnS9ikNeQ4R" name="Scarpa Cyrus 2 Mid GTX" alt="Scarpa Cyrus 2 Mid GTX brown hiking boots" src="https://cdn.mos.cms.futurecdn.net/SNsaqFEMPkBwnS9ikNeQ4R-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>The boots have great grip! Despite my clumsy disposition, I didn’t fall over once. I made my way through mud, sand and over rocks and felt very stable. The legs dug into the ground very well but didn’t hold on to any debris. I tested these boots during fall, and as the weather got wetter where I live, I didn’t have any issues on the slippery ground. </p><h2 id="support">Support</h2><p>Despite the lack of cushioning I mentioned, my feet felt supported. I have high arches and didn’t experience any aches, and I felt my posture was well supported too. Your posture while walking is directly impacted by your footwear, so I’m happy with the results I got. </p><p>The ankle support was impressive, and even when I felt my balance wavering on uneven ground, I knew I had all the support I needed to keep me upright. </p><h2 id="flex">Flex</h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:2560px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="4L9sSn9P7qHP2hKYx8sXzQ" name="Scarpa Cyrus 2 Mid GTX" alt="Scarpa Cyrus 2 Mid GTX brown hiking boots" src="https://cdn.mos.cms.futurecdn.net/4L9sSn9P7qHP2hKYx8sXzQ-1920-80.jpg" mos="" align="middle" fullscreen="" width="2560" height="1440" attribution="" endorsement="" class="inline" /></p></div></div><figcaption itemprop="caption description" class=" inline-layout"><span class="credit" itemprop="copyrightHolder">(Image credit: Tom's Guide)</span></figcaption></figure><p>Since this is a thinner sole, there’s plenty of flex. The boots were bending with the movement of my feet, and I enjoyed how this made my strides feel natural and unrestricted. </p><p>Flex isn’t always a great thing in walking boots, and some stiffness can offer stability. However, since these boots are designed for shorter hikes and casual walks, it’s good to have some natural movement in your feet. </p><h2 id="waterproofing">Waterproofing</h2><p>Boy, was I thankful for the waterproofing on the Scarpa Cyrus 2 Mid GTX boots. Whilst on a long walk, I found myself at the beach once I emerged from the trees. What a lovely sight, but to get down onto the sand I had to cross a small inlet. That was no big deal for these boots. I was in water just up to the laces, and my feet stayed completely dry. </p><h2 class="article-body__section" id="section-scarpa-cyrus-2-mid-gtx-review-maintenance"><span>Scarpa Cyrus 2 Mid GTX review: Maintenance</span></h2><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:1920px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="CBGawmVYy5rFuuEqwNKBmA" name="Scarpa Cyrus 2 Mid GTX" alt="Scarpa Cyrus 2 Mid GTX brown hiking boots" src="https://cdn.mos.cms.futurecdn.net/CBGawmVYy5rFuuEqwNKBmA-1920-80.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 Scarpa Cyrus 2 Mid GTX hiking boots are easy to maintain, just like any pair of hiking boots. Since the upper is made from Nubuck leather, you should ensure they’re completely dry before storing them away. I brushed the dirt off my boots once dry, and they looked as good as new. </p><h2 class="article-body__section" id="section-scarpa-cyrus-2-mid-gtx-review-verdict"><span>Scarpa Cyrus 2 Mid GTX review: Verdict</span></h2><p>The Scarpas have good waterproofing, keep my feet dry even in the sea, have a durable build with a Nubuck leather upper, and are comfortable straight out of the box. The boots are lightweight and very flexible, making walking feel very natural. The traction and support also made the journey in these boots very relaxing, knowing I was stable with every step. </p><p>That said, they’re not totally perfect. The cushioning of the insole is minimal, and while this didn’t impact my experience, those with sensitive soles may find them a little uncomfortable. The fit is also a little snug. Sizing up should solve this, but those with wider feet may want to look elsewhere. </p><p>Nevertheless, the Scarpa Cyrus 2 Mid GTX hiking boots are now a firm favorite of mine. I’ve always wanted a pair of boots that I can rely on when the walk requires more than a regular sneaker but doesn’t need mountaineering boots — and now I have them. </p>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
                                <item>
                                                            <title><![CDATA[ I’ve tested 16 new carbon plate running shoes this year, but my favorite is still the Puma Fast-R 3 — it’s reduced by $100 right now ]]></title>
                                                                                                <dc:content><![CDATA[ <p>Carbon plate running shoes have changed the game when it comes to race day, with their propulsive, efficient rides helping runners of all levels break personal records at all distances.</p><p>There are so many great carbon plate racers available it’s hard for a shoe to stand out from the crowd, and more keep coming — I’ve tested 16 new ones in 2026 already.</p><p>However, the Puma Fast-R Nitro Elite 3 <em>does</em> stand out, both for its looks and its performance. It’s still my go-to racer over a year after it came out and <a href="https://us.puma.com/us/en/pd/fast-r-nitro-elite-3-mens-road-running-shoes/312060?" target="_blank" rel="nofollow">you can get it for $199 in the Puma sale right now</a>, a hefty $100 saving.</p><div class="product"><a data-dimension112="cf2387ee-c93e-11f1-8dac-9b80399f2383" data-action="Deal Block" data-label="Fast-R Nitro Elite 3" data-dimension48="Fast-R Nitro Elite 3" data-dimension25="$199" href="https://us.puma.com/us/en/pd/fast-r-nitro-elite-3-mens-road-running-shoes/312060?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="suWtb7xw9PohDdD7uw25NQ" name="Puma Fast-R Nitro Elite 3" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/suWtb7xw9PohDdD7uw25NQ-1920-80.png" mos="" align="middle" fullscreen="" width="750" height="750" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://us.puma.com/us/en/pd/fast-r-nitro-elite-3-mens-road-running-shoes/312060?" target="_blank" rel="nofollow" data-dimension112="cf2387ee-c93e-11f1-8dac-9b80399f2383" data-action="Deal Block" data-label="Fast-R Nitro Elite 3" data-dimension48="Fast-R Nitro Elite 3" data-dimension25="$199">Fast-R Nitro Elite 3: was $300 now $199</a></strong><br />All colors of the Puma Fast-R 3 are reduced to $199 in the Puma sale, and there is a wide range of sizes still available. It's still not exactly cheap, but that's a great price for what I think is the best racing shoe on the market right now.<a class="view-deal button" href="https://us.puma.com/us/en/pd/fast-r-nitro-elite-3-mens-road-running-shoes/312060?" target="_blank" rel="nofollow" data-dimension112="cf2387ee-c93e-11f1-8dac-9b80399f2383" data-action="Deal Block" data-label="Fast-R Nitro Elite 3" data-dimension48="Fast-R Nitro Elite 3" data-dimension25="$199">View Deal</a></p></div><p>I was wowed by the Puma Fast-R 3 from the moment I first tested it. I ran a 15-minute 5K parkrun in it out of the box, then used it to run a 2:26 at the London Marathon a week later.</p><p>Since then I’ve used it to run my 5-mile PR and many other races and hard training sessions, and I’m on my second pair of the shoe.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="H7QtF35Z9D26sCbn5aJhMV" name="Puma Fast-R Nitro Elite 3" alt="Puma Fast-R Nitro Elite 3" src="https://cdn.mos.cms.futurecdn.net/H7QtF35Z9D26sCbn5aJhMV-1920-80.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>Even in the crowded carbon market the Puma Fast-R 3 has a unique ride thanks to the extended carbon plate and aggressively rockered geometry that helps you to keep pushing and hold your goal race pace all the way to the finish line.</p><p>I’ve spent the last few months training for the Frankfurt Marathon when I’ll be wearing the Fast-R 3 again to try and set a new PR. </p><div><blockquote><p>I’ve spent the last few months training for the Frankfurt Marathon when I’ll be wearing the Fast-R 3 again to try and set a new PR. </p></blockquote></div><p>It’s an expensive shoe and I wouldn't expect to get more than 200-300 miles out of a pair before they’re past their best, but on race day I just want the fastest shoe on my feet.</p><p>I’ve not seen big discounts crop up on the Fast-R 3 all that often since it came out last year, so the $100 saving you can get in the Puma sale right now is exceptional.</p><p>It is a shame, however, that it’s not currently included in the <a href="https://us.puma.com/us/en/sale/all-sale" target="_blank" rel="nofollow">STOCKUP promotion on the Puma site</a>, where you get an extra 20% off for buying two sale items, 30% for three, and 40% for four.</p><p>That said, if you want to add some running apparel and accessories to your basket alongside the Fast-R 3, you can stock up on socks, tees and shorts in the sale for less.</p><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Home+Tech&amp;view_mode=carousel&amp;widget_title=Top+Deals+Handpicked+by+Our+Editors&amp;widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&amp;bg_color=light_blue" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters {      display: flex;      gap: 12px;      justify-content: center;      flex-wrap: wrap;    }    .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);      display: -webkit-box;      -webkit-line-clamp: 2;      -webkit-box-orient: vertical;      overflow: hidden;    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    .tg-df-container .tg-df-card-cta.tg-df-cta-savings-squad {      background-color: #3c8d0d;    }    .tg-df-card:hover .tg-df-card-cta.tg-df-cta-savings-squad,    .tg-df-card-cta.tg-df-cta-savings-squad:hover {      background-color: #2b6509;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 0;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 0 16px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }            .tg-df-filters {        width: calc(100% + 32px);        margin: 0 -16px;        padding: 0 16px 4px 16px;        display: flex;        justify-content: flex-start;        gap: 8px;        flex-wrap: nowrap;        overflow-x: auto;        -webkit-overflow-scrolling: touch;        scrollbar-width: none;      }      .tg-df-filters::after {        content: "";        display: block;        flex: 0 0 8px;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }            .tg-df-sort-wrapper {        flex: 0 0 max(42%, 130px);        min-width: 0;      }      .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;        -webkit-line-clamp: 3;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        -webkit-line-clamp: 3;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 16px;      text-align: center;      width: 100%;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: #f8fafc;      border-color: #cbd5e1;    }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right {      background-color: rgba(255, 255, 255, 0.4);      border: none;      box-shadow: none;      backdrop-filter: blur(4px);      -webkit-backdrop-filter: blur(4px);    }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right { right: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-right { right: 0; }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left:hover,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);      border: none;    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-carousel-roundels::after {      content: "";      flex: 0 0 32px;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;      transition: font-weight 0.2s;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-label {      font-weight: 700;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;      display: inline-flex;      align-items: center;      justify-content: center;      min-height: 36px;      box-sizing: border-box;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::after {      content: "";      flex: 0 0 32px;    }    .tg-df-grid-wrapper {      position: relative;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card {      flex: 0 0 auto;      width: 100px;      border-radius: 15px;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      border: 2px solid #1e293b;      background: white;      color: #1e293b;      display: flex;      flex-direction: column;      justify-content: center;      align-items: center;      font-weight: 600;      font-size: 14px;      cursor: pointer;      padding: 16px;      text-align: center;      transition: all 0.2s;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card:hover {      background: #1e293b;      color: white;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      -webkit-line-clamp: 2;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {      -webkit-line-clamp: 3;    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.45);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #5aaf0b; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #4a9109; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>          \x3C/div>          \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">      \x3Cdiv class="tg-df-top-bar">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>                \x3Cdiv class="tg-df-settings-wrapper">          \x3Cbutton type="button" class="tg-df-settings-btn" aria-label="Settings" id="tg-df-settings-toggle">            \x3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20">                \x3Cpath d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.73 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .43-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.49-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/>            \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-settings-dropdown-backdrop" id="tg-df-settings-backdrop">\x3C/div>          \x3Cdiv class="tg-df-settings-dropdown" id="tg-df-settings-panel">            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Search Region\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-region-select">                \x3Coption value="auto">🌍 Auto-detect\x3C/option>                \x3Coption value="US">🇺🇸 United States (US)\x3C/option>                \x3Coption value="GB">🇬🇧 United Kingdom (UK)\x3C/option>                \x3Coption value="CA">🇨🇦 Canada (CA)\x3C/option>                \x3Coption value="AU">🇦🇺 Australia (AU)\x3C/option>                \x3Coption value="DE">🇩🇪 Germany (DE)\x3C/option>                \x3Coption value="FR">🇫🇷 France (FR)\x3C/option>                \x3Coption value="IT">🇮🇹 Italy (IT)\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Retailer\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-retailer-select">                \x3Coption value="">All Retailers\x3C/option>                \x3Coption value="Amazon">Amazon\x3C/option>                \x3Coption value="Walmart">Walmart\x3C/option>                \x3Coption value="Best Buy">Best Buy\x3C/option>                \x3Coption value="Target">Target\x3C/option>                \x3Coption value="John Lewis">John Lewis\x3C/option>                \x3Coption value="Currys">Currys\x3C/option>                \x3Coption value="Argos">Argos\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Offer Type\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-offer-type-select">                \x3Coption value="">All Offers\x3C/option>                \x3Coption value="amazon_prime">Amazon Prime\x3C/option>                \x3Coption value="recommended_promo">Recommended Promo\x3C/option>                \x3Coption value="amazon_lightning">Amazon Lightning Deal\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Result Count\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-rows-select">                \x3Coption value="3">3 Items\x3C/option>                \x3Coption value="4">4 Items\x3C/option>                \x3Coption value="6">6 Items\x3C/option>                \x3Coption value="12" selected>12 Items\x3C/option>                \x3Coption value="24">24 Items\x3C/option>                \x3Coption value="48">48 Items\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Deal Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Only show products with active offers or previous prices (was_price)\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-deal-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Editor Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Enable multi-select to copy deals to CMS\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-editor-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">View Mode\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-view-mode-select">                \x3Coption value="auto">Auto Collection\x3C/option>                \x3Coption value="carousel">Carousel\x3C/option>                \x3Coption value="savings_squad">Savings Squad\x3C/option>                \x3Coption value="grid">Grid (Columns)\x3C/option>                \x3Coption value="row">Row (List)\x3C/option>              \x3C/select>            \x3C/div>          \x3C/div>        \x3C/div>      \x3C/div>      \x3Cdiv class="tg-df-filters">        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M9 3L5 6.99h3V14h2V6.99h3L9 3zm7 14.01V10h-2v7.01h-3L15 21l4-3.99h-3z"/>          \x3C/svg>          \x3Cselect class="tg-df-sort-select" aria-label="Sort Deals">            \x3Coption value="date_desc">Newest First\x3C/option>            \x3Coption value="best_match">Sort by: Match\x3C/option>            \x3Coption value="price_asc">Price Low to High\x3C/option>            \x3Coption value="price_desc">Price High to Low\x3C/option>            \x3Coption value="discount_desc">Biggest Discount\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>        \x3C/div>      \x3C/div>    \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();            if (['carousel', 'carousel-compact', 'auto', 'grid', 'row'].includes(this.getViewMode())) { this.loadCarouselSpreadsheet(); }        }        getViewMode() {          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          if (mode === 'carousel' || mode === 'auto' || mode === 'grid' || mode === 'row') {             if (mode === 'carousel') this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container') && mode === 'carousel') {               this.root.classList.add('is-carousel');             } else if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Everything';             if (this.discountFilter && !params.has('min_discount_ratio')) {               this.discountFilter.value = '5';             }          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (params.has('bg_color')) {            const bg = params.get('bg_color');            if (bg === 'white') {              this.root.style.setProperty('background-color', '#ffffff', 'important');            } else if (bg === 'transparent') {              this.root.style.setProperty('background-color', 'transparent', 'important');            } else if (bg === 'light_blue') {              this.root.style.setProperty('background-color', '#E7F0FF', 'important');            }          } else {             this.root.style.removeProperty('background-color');          }                    if (params.has('view_mode')) {            if (this.viewModeSelect) {              this.viewModeSelect.value = params.get('view_mode');            } else {              this.viewModeOverride = params.get('view_mode');            }          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'discount_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            this.searchInput.value = this.currentQuery;          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'discount_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const roundels = this.root.querySelectorAll('.tg-df-carousel-cat.original-hardcoded');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              if (this.getViewMode() === 'savings_squad' && this.autocompleteDropdown && this.airedaleTags && query.length > 0) {                 const matches = this.airedaleTags.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase()).slice(0, 5);                 if (matches.length > 0) {                    this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                    this.autocompleteDropdown.classList.add('active');                 } else {                    this.autocompleteDropdown.classList.remove('active');                 }              } else if (this.autocompleteDropdown) {                 this.autocompleteDropdown.classList.remove('active');              }              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  this.deals = [];                  this.render();                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                this.activeDealTag = null;                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });              this.activeDealTag = null;              this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.fetchDeals(query);              }            });          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = this.viewModeSelect.value === 'savings_squad' ? 'date_desc' : 'discount_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }                async loadCarouselSpreadsheet() {          try {              const parseCSVRow = (str) => {                  let result = [], cur = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (inQuotes) {                          if (char === '"') {                              if (str[i + 1] === '"') { cur += '"'; i++; }                              else { inQuotes = false; }                          } else { cur += char; }                      } else {                          if (char === '"') { inQuotes = true; }                          else if (char === ',') { result.push(cur); cur = ''; }                          else { cur += char; }                      }                  }                  result.push(cur); return result;              };              const parseCSV = (str) => {                  const rows = []; let curRow = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (char === '"') inQuotes = !inQuotes;                      if ((char === '\n' || char === '\r') && !inQuotes) {                          if (char === '\r' && str[i+1] === '\n') i++;                          if (curRow) rows.push(parseCSVRow(curRow));                          curRow = '';                      } else { curRow += char; }                  }                  if (curRow) rows.push(parseCSVRow(curRow));                  return rows;              };              const preloadedCSV = decodeURIComponent(escape(atob("LCwxLDIsMyw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNQ0KUm91bmRlbCB0ZXh0LEFsbCxUVnMsRm9vdHdlYXIsQXBwYXJlbCxNYXR0cmVzZXMsQXBwbGlhbmNlcyxXZWFyYWJsZSB0ZWNoLEhlYWRwaG9uZXMsU21hcnQgSG9tZSxTcGVha2VycyxMYXB0b3BzLFRhYmxldHMsQ29tcHV0aW5nLFBob25lcyxHYW1pbmcsTGVnbw0KUm91bmRlbCBpbWFnZSxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL2FpLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL3R2cy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvN2IzYTIyNGIwNzk2M2M2MjdiNmI5MDliZDc4MzM4MzZlMDJmZjgxOS5qcGcud2VicCxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy84NGRhYzVkNDhlZDJkNDQ4NTU5ZWJhNjdhY2U4MzE0Y2M2N2NjZDk0LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vc2hvcC1hc3NldHMvY2Fyb3VzZWwvbWF0dHJlc3Nlcy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvNzY4ZTk3Y2ViMDcxODAxZmFlMjA5MTBkMDgyMGIxNmY3NDdhZjkzOS5qcGcud2VicCxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL3dlbGxuZXNzLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL2hlYWRwaG9uZXMuanBnLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzg5NTM1YmVlYmUyMGRiYmQ0YTM0NmQ2ZDZiZGZlOTFkOGE4ODRhMjEuanBnLndlYnAsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9zaG9wLWFzc2V0cy9jYXJvdXNlbC9hdWRpby5qcGcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9zaG9wLWFzc2V0cy9jYXJvdXNlbC9sYXB0b3BzLmpwZyxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy8yMzk3NTY0ZWQ3YTVmZjk0N2U5YjZiMzBlNTRmNDc0OTRiODQxZjg5LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vc2hvcC1hc3NldHMvY2Fyb3VzZWwvY29tcHV0aW5nLmpwZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL3Bob25lcy5wbmcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9zaG9wLWFzc2V0cy9jYXJvdXNlbC9nYW1pbmcucG5nLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzRmNmM2MjFjYWMwYmMxYTg1ZDU5M2UzNTk0YmE1YjM0OWVmZmQyOTIuanBnLndlYnANClNlYXJjaCBRdWVyeSxFdmVyeXRoaW5nLFRlbGV2aXNpb25zLCJTbmVha2VycywgcnVubmluZyBzaG9lcywgc2FuZGFscyIsQ2xvdGhpbmcsTWF0dHJlc3NlcyxIb21lIEFwcGxpYW5jZXMsV2VhcmFibGVzICYgRml0bmVzcyBUZWNoLEhlYWRwaG9uZXMsSG9tZSBUZWNoLFNwZWFrZXJzLExhcHRvcHMsVGFibGV0cyxDb21wdXRpbmcsUGhvbmVzLEdhbWluZyxDb25zdHJ1Y3Rpb24gVG95cw0KRGlzY291bnQgQW1vdW50LG1pbiA1JSxtaW4gMTAlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUNClByaWNlIFJhbmdlLCwsLCxtaW4gJDQwMCwsLCxtaW4gJDI1LCxtaW4gJDMwMCwsLG1pbiAkMTAwLCwNCkJyYW5kIFNlbGVjdGlvbiwsLCwsLCwsLCwsLCwsLCwNCkZpbHRlciBidXR0b25zLCwsLCwsLCwsLCwsLCwsLA0KMSxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMNCjIsQW1hem9uIGRlYWxzLFVuZGVyICQxMDAwLDUwJSBvZmYsQWRpZGFzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsNTAlIG9mZixBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscw0KMyxPdmVyICQ0MDAsVW5kZXIgJDUwMCxIb2thLE5pa2UsU2FhdHZhLE5pbmphLDQwJSBvZmYsSkxhYiwsSkJMLERlbGwsLEFzdXMsQXBwbGUsQ29uc29sZXMsU3RhciBXYXJzDQo0LFVuZGVyICQxMDAwLDUwJSBvZmYsU2tlY2hlcnMsVW5kZXIgQXJtb3VyLEhlbGl4LFNoYXJrLEdhcm1pbixBbmtlciBTb3VuZGNvcmUsUmluZyxTb25vcyxBcHBsZSxBcHBsZSxUUC1saW5rLFNhbXN1bmcsQWNjZXNzb3JpZXMsVW5kZXIgJDI1DQo1LFVuZGVyICQ1MDAsTEcsQXNpY3MsQ29sdW1iaWEsRHJlYW1DbG91ZCxLZXVyaWcsQXBwbGUsU29ueSxHb3ZlZSxUcmliaXQsTGVub3ZvLFNhbXN1bmcsRWVybyxHb29nbGUsR2FtZXMsVW5kZXIgJDUwDQo2LDUwJSBvZmYsU2Ftc3VuZyxOaWtlLFBhdGFnb25pYSxOZWN0YXIsRGUnTG9uZ2hpLEFtYXpmaXQsQXBwbGUsS2FzYSBzbWFydCxTb255LEFsaWVud2FyZSxUQ0wsTmV0Z2VhcixNb3Rvcm9sYSxOaW50ZW5kbyxCb3RhbmljYWxzDQo3LEFtYXpvbixIaXNlbnNlLE5ldyBCYWxhbmNlLEFyYyd0ZXJ5eCxUZW1wdXItcGVkaWMsRHlzb24sRml0Yml0LEJlYXRzLFBoaWxpcHMgSHVlLEFua2VyLEFjZXIsT25lUGx1cyxEZWxsLE9uZVBsdXMsU29ueSxEaXNuZXkNCjgsQXBwbGUsVENMLEFkaWRhcyxDYXJoYXJ0dCxCZWFyLEJpc3NlbGwsU2Ftc3VuZyxFYXJmdW4sQmxpbmssQmVhdHMsTVNJLE1pY3Jvc29mdCxBY2VyLE5vdGhpbmcsWGJveCxNYXJ2ZWwNCjksLFNvbnksU2F1Y29ueSxUaGUgTm9ydGggRmFjZSxTaWVuYSxOdXRyaWJ1bGxldCxPdXJhLFNhbXN1bmcsR29vZ2xlIE5lc3QgLE1hcnNoYWxsLFNhbXN1bmcsTGVub3ZvLExlbm92bywsLFBva2Vtb24NCjEwLCxSb2t1LEJpcmtlbnN0b2NrLENSWiBZb2dhLFdpbmtCZWRzLEJsYWNrIGFuZCBEZWNrZXIsUmluZ2Nvbm4sQ01GLEV1ZnksU2Ftc3VuZyxNaWNyb3NvZnQsUmVNYXJrYWJsZSxBbGllbndhcmUsLCwNCjExLCwsQnJvb2tzLFRoZSBHeW0gUGVvcGxlLEJyb29rbHluIGJlZGRpbmcsTmVzcHJlc3NvLCwxTW9yZSxBcmxvLCxSYXplciwsQ29yc2FpciwsLA0KMTIsLCxDcm9jcywsRWlnaHQgU2xlZXAsQ3Vpc2luYXJ0LCxKQkwsLCwsLEhQLCwsDQpOb3RlcywsLCwsLCwsLCwsLCwsLCwNCiwsIlByaW9yaXRpc2UgYmlnZ2VzdCAlLyQgZGlzY291bnQsIFR2cyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiB0aGUgbW9zdCBwb3B1bGFyIGV2ZW4gaWYgdGhleSBhcmUgc3RpbGwgZXhwZW5zaXZlIiwiTm8gcGF0dGVybiB0byBwcmljaW5nL2Rpc2NvdW50LCByZWFkZXJzIG1haW5seSBzaG9wIGJ5IGJyYW5kL3JlY29nbmlzYWJsZSBzaG9lcyIsIk5vIHBhdHRlcm4gdG8gcHJpY2luZy9kaXNjb3VudCwgcmVhZGVycyBtYWlubHkgc2hvcCBieSBicmFuZCIsIkEgbGFiZWwgd2lsbCBkZWZpbml0ZWx5IGhlbHAgaGVyZSBlLmcuIGJlc3QgZm9yIHNpZGUgc2xlZXBlciwgYmVzdCBtZW1vcnkgZm9hbSIsIkFwcGxpYW5jZXMgaXMgYSBiaWcgY2F0ZWdvcnksIGlzIGl0IHBvc3NpYmxlIHRvIHNwbGl0IGludG8ga2l0Y2hlbiBhcHBsaWFuY2VzLCBmbG9vcmNhcmUsIGFpciBoZWFsdGgvY29vbGluZz8gT3Igc2ltaWxhciIsIkZvY3VzIG9uIHZhbHVlIGZvciBtb25leSwgR2FybWlucyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiBwb3B1bGFyIGV2ZW4gdGhvdWdoIHRoZXkgYXJlIHN0aWxsICQ1MDAiLCwsLCxJbmNsdWRlIEtpbmRsZXMsSSB3b3VsZCBpbmNsdWRlIHdpZmkgcm91dGVycyBoZXJlIGluc3RlYWQgb2Ygc21hcnQgaG9tZSxDYW4gd2Ugc3VyZmFjZSBwaG9uZSBwcm92aWRlciBkZWFscz8gVC1tb2JpbGUgYW5kIHZlcml6b24gd291bGQgbWFrZSBhIGxvdCBtb3JlIG1vbmV5IHRoYW4gQW1hem9uLCwNCiwsaGF2aW5nIGEgJ2Jlc3QgZm9yJyBsYWJlbCB3b3VsZCBiZSBoZWxwZnVsIGUuZy4gYmVzdCBmb3IgYnJpZ2h0IHJvb20sQ2FuIHdlIHN0b3Aga2lkcyBzaG9lcyBmcm9tIHB1bGxpbmcgdGhyb3VnaD8sIldpbGwgdGhpcyBpbmNsdWRlIGFjY2Vzc29yaWVzIGUuZy4gY2FwcywgYmFncywgaWYgc28gbWFrZSBzdXJlIHRoZXNlIGFyZSBtaXhlZCB0aHJvdWdob3V0IGNsb3RoaW5nIGRlYWxzIixXaWxsIHRoaXMgaW5jbHVkZSB0b3BwZXJzIGFuZCBwaWxsb3dzPyBTZWVpbmcgbW9yZSBtb21lbnR1bSB3aXRoIHRoaXMgY2F0ZWdvcnkgcmVjZW50bHkgc28gYSBiZWRkaW5nIHRhYiBtaWdodCB3b3JrLCwiTmVlZCB0byBtYWtlIHN1cmUgYmFuZHMsIHNjcmVlbiBwcm90ZWN0b3JzIGV0Yy4gZG9uJ3QgcHVsbCBpbnRvIGhlcmUiLCwsLCwsLCwsDQosLCJQcmlvcml0aXNlIDY1JycgYW5kIDU1JyBpbmNoIFRWcywgdGhlbiBiaWdnZXIgc2NyZWVucyBiZWZvcmUgdGhlIHNtYWxsZXIgc2l6ZXMiLCwsUXVlZW4gaXMgdGhlIG1vc3QgcG9wdWxhciBzaXplIGluIHRoZSBVUyAtIHByaW9yaXRpc2UgZGVhbHMgZm9yIHRoaXMgc2l6ZSwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpDYXRlZ29yaWVzIHRvIGNvbnNpZGVyLCxQcm9kdWN0cyBpbmNsdWRlZCwsLCwsLCwsLCwsLCwsDQpVbmRlciAkNTA/LCxBaXIgdGFncywsLCwsLCwsLCwsLCwsDQosLFBvcnRhYmxlIGNoYXJnZXJzL3dpcmVsZXNzIGNoYXJnZXJzLCwsLCwsLCwsLCwsLCwNCiwsIldhdGVyIGJvdHRsZXMgKHN0YW5sZXlzLCBPd2FsYSwgSHlkcm8gZmxhc2ssIFlldGkpIiwsLCwsLCwsLCwsLCwsDQosLEhhbmQgaGVsZCBmYW5zLCwsLCwsLCwsLCwsLCwNCiwsLCwsLCwsLCwsLCwsLCwNCmhvbWUgb2ZmaWNlLCxvZmZpY2UgY2hhaXJzLCwsLCwsLCwsLCwsLCwNCiwsc3RhbmRpbmcgZGVza3MsLCwsLCwsLCwsLCwsLA0KLCxtb25pdG9ycywsLCwsLCwsLCwsLCwsDQosLEtleWJvYXJkcywsLCwsLCwsLCwsLCwsDQosLGRvY2tpbmcgc3RhdGlvbiwsLCwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpHYW1pbmcsLENvbnNvbGVzLCwsLCwsLCwsLCwsLCwNCiwsQWNjZXNzb3JpZXMsLCwsLCwsLCwsLCwsLA0KLCxHYW1lcywsLCwsLCwsLCwsLCwsDQosLENvdWxkIGluY2x1ZGUgTGVnbz8sLCwsLCwsLCwsLCwsLA==")));              const text = preloadedCSV;              const parsed = parseCSV(text);                            const rowsByName = {};              let filterStart = -1;              parsed.forEach((rc, i) => {                 if (rc && rc.length > 0 && rc[0]) rowsByName[rc[0]] = rc;                 if (rc && rc.length > 0 && rc[0] === 'Filter buttons') filterStart = i;              });                            const cols = [];              if(rowsByName['Roundel text']) {                const headerRow = rowsByName['Roundel text'];                for(let col = 1; col < headerRow.length; col++) {                   let label = headerRow[col];                   if (!label) continue;                                      let q = rowsByName['Search Query'] && rowsByName['Search Query'][col] ? rowsByName['Search Query'][col] : '';                   let img = rowsByName['Roundel image'] && rowsByName['Roundel image'][col] ? rowsByName['Roundel image'][col] : '';                   let ds = rowsByName['Discount Amount'] && rowsByName['Discount Amount'][col] ? rowsByName['Discount Amount'][col] : '';                   let pr = rowsByName['Price Range'] && rowsByName['Price Range'][col] ? rowsByName['Price Range'][col] : '';                   let rt = rowsByName['Retailer'] && rowsByName['Retailer'][col] ? rowsByName['Retailer'][col] : '';                   let ot = rowsByName['Offer Type'] && rowsByName['Offer Type'][col] ? rowsByName['Offer Type'][col] : '';                                      let filters = [];                   if(filterStart > 0) {                     for(let r = filterStart + 1; r < parsed.length; r++) {                         if(!parsed[r] || parsed[r][0] === 'Notes' || parsed[r][0] === 'Categories to consider') break;                         let f = parsed[r][col];                         if(f) filters.push(f);                     }                   }                   cols.push({ label, img, q, ds, pr, rt, ot, filters });                }              }              this.carouselData = cols;              if (this.carouselData && this.carouselData.length > 0) {                 const isMatched = this.carouselData.some(c => c.q === this.currentQuery || c.label === this.currentQuery);                 if (!isMatched) {                    const first = this.carouselData[0];                    this.currentQuery = first.q || first.label;                    if (this.priceFilter) this.priceFilter.value = 'all';                    if (this.customPriceMin) this.customPriceMin.value = '';                    if (this.customPriceMax) this.customPriceMax.value = '';                    let dPr = first.pr || 'all';                    if (typeof dPr === 'string' && dPr !== 'all') {                       let prLower = dPr.toLowerCase();                       if (prLower.includes('min') || prLower.includes('over')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else if (prLower.includes('max') || prLower.includes('under')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       }                    }                    let dAm = '0';                    if(first.ds && typeof first.ds === 'string') {                       let m = first.ds.match(/(\d+)/);                       if(m) dAm = m[1];                    }                    if (this.discountFilter) this.discountFilter.value = dAm;                    if (this.offerTypeSelect) this.offerTypeSelect.value = first.ot || '';                    if (this.retailerSelect) this.retailerSelect.value = first.rt || '';                    this.selectedBrands = [];                    if (this.brandDropdown) {                        const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                        chks.forEach(chk => chk.checked = false);                    }                    if (this.searchInput) this.searchInput.value = this.currentQuery;                 }              }              this.renderCarouselUI();          } catch(e){ console.warn(e); }        }                renderCarouselUI() {           const roundelWrapper = this.root.querySelector('.tg-df-carousel-roundels');           if(!roundelWrapper || !this.carouselData) return;                      let html = '';           this.carouselData.forEach(r => {              const q = r.q || r.label;              const isActive = (this.currentQuery === q || this.currentQuery === r.label) ? 'active' : '';              const imgHtml = r.img ? `\x3Cimg src="${r.img}" alt="${r.label}" />` : `\x3Csvg width="32" height="32" fill="#1F69FF" viewBox="0 0 24 24">\x3Cpath d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/>\x3C/svg>`;              html += `                \x3Cdiv class="tg-df-roundel tg-df-carousel-cat ${isActive}" data-label="${this.escapeHTML(r.label)}">                  \x3Cdiv class="tg-df-roundel-img-box">${imgHtml}\x3C/div>                  \x3Cspan class="tg-df-roundel-label">${this.escapeHTML(r.label)}\x3C/span>                \x3C/div>              `;           });           roundelWrapper.innerHTML = html;                      // Rebind clicks           const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');           roundels.forEach(rNode => {             rNode.addEventListener('click', () => {                const r = this.carouselData.find(c => c.label === rNode.getAttribute('data-label'));                 if(!r) return;                                  if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: r.label,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = r.q || r.label;                const labelTitle = this.root.querySelector('#tg-df-carousel-title-label');                if (labelTitle) labelTitle.textContent = 'Best ' + this.currentQuery;                if (this.priceFilter) this.priceFilter.value = 'all';                if (this.customPriceMin) this.customPriceMin.value = '';                if (this.customPriceMax) this.customPriceMax.value = '';                let dPr = r.pr || 'all';                if (typeof dPr === 'string' && dPr !== 'all') {                   let prLower = dPr.toLowerCase();                   if (prLower.includes('min') || prLower.includes('over')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMin) this.customPriceMin.value = m[1];                   } else if (prLower.includes('max') || prLower.includes('under')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMax) this.customPriceMax.value = m[1];                   }                }                                let discountAmount = '0';                if(r.ds && typeof r.ds === 'string') {                   let m = r.ds.match(/(\d+)/);                   if(m) discountAmount = m[1];                }                if (this.discountFilter) this.discountFilter.value = discountAmount;                if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                                // Clear brands                    this.selectedBrands = [];                    if (this.brandDropdown) {                    const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                    chks.forEach(chk => chk.checked = false);                }                                if (this.searchInput) this.searchInput.value = this.currentQuery;                                roundels.forEach(ro => ro.classList.remove('active'));                if (rNode) rNode.classList.add('active');                                this.renderCarouselFilters(r);                this.fetchDeals(this.currentQuery);             });           });                      // Auto-highlight active           const activeR = this.carouselData.find(c => c.q === this.currentQuery || c.label === this.currentQuery);           if(activeR) this.renderCarouselFilters(activeR);        }                renderCarouselFilters(r) {           const filtersWrap = this.root.querySelector('.tg-df-carousel-filters-wrap');           if(!filtersWrap) return;                      let html = `\x3Cbutton class="tg-df-carousel-filter-btn" data-type="all">All\x3C/button>`;                      r.filters.forEach(f => {              let fL = f.toLowerCase();              let icon = '';              let logic = `data-type="custom" data-v="${this.escapeHTML(f)}"`;              if (fL === 'amazon deals' || fL === 'prime deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>`;              } else if (fL === 'lightning deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>`;              } else {                 if (fL.includes('lightning')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-zap">\x3Cpolygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2">\x3C/polygon>\x3C/svg>`;                 } else if (fL.includes('% off')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>`;                 } else if (fL.includes('under') || fL.includes('min ')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>`;                 }                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>${icon} ${this.escapeHTML(f)}\x3C/button>`;              }           });                      filtersWrap.innerHTML = html;                      const btns = filtersWrap.querySelectorAll('button');           btns.forEach(b => {             b.addEventListener('click', () => {                const type = b.getAttribute('data-type');                if (type === 'custom') {                   const v = b.getAttribute('data-v');                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-custom-${(v||'').toLowerCase().replace(/[^a-z0-9]+/g, '-')}`, name: 'Custom Filter', label: v });                }                if (type === 'all') {                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: 'filter-clear-all', name: 'Clear all', label: 'Clear all filters' });                   // reset everything                   btns.forEach(btn => btn.classList.remove('active'));                   b.classList.add('active');                                      // Reset prices                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   if (this.brandDropdown) {                     const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                     chks.forEach(chk => chk.checked = false);                   }                } else {                   const v = b.getAttribute('data-v');                   const fL = v.toLowerCase();                                      let mapRet = ['amazon', 'walmart', 'best buy', 'target', 'john lewis', 'currys', 'argos'];                   const getCategory = (s) => {                      if (s === 'lightning deals' || s === 'amazon deals' || s === 'prime deals') return 'offer';                      if (s.includes('% off')) return 'discount';                      if (s.includes('under') || s.includes('over') || s.includes('min') || s.includes('max')) return 'price';                      if (mapRet.includes(s)) return 'retailer';                      return 'brand';                   };                   const cat = getCategory(fL);                   const wasActive = b.classList.contains('active');                   if (cat !== 'brand') {                      btns.forEach(btn => {                          if (btn === b) return;                          if (btn.getAttribute('data-type') === 'all') return;                          const bV = btn.getAttribute('data-v');                          if (!bV) return;                          if (getCategory(bV.toLowerCase()) === cat) btn.classList.remove('active');                      });                   }                   if (wasActive) b.classList.remove('active');                   else b.classList.add('active');                   let anyActive = Array.from(btns).some(btn => btn !== btns[0] && btn.classList.contains('active'));                   if (!anyActive) {                       btns[0].click();                       return;                   } else {                       btns[0].classList.remove('active');                   }                                      if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   btns.forEach(btn => {                       if (!btn.classList.contains('active') || btn.getAttribute('data-type') === 'all') return;                       const vv = btn.getAttribute('data-v');                       const vl = vv.toLowerCase();                                              if (vl === 'lightning deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_lightning';                       } else if (vl === 'amazon deals' || vl === 'prime deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_prime';                       } else if (vl.includes('% off')) {                          let m = vl.match(/(\d+)%/);                          if (m && this.discountFilter) this.discountFilter.value = m[1];                       } else if (vl.includes('under') || vl.includes('max')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       } else if (vl.includes('min') || vl.includes('over')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else {                          let foundR = mapRet.find(x => x === vl);                          if (foundR) {                             let realR = ['Amazon', 'Walmart', 'Best Buy', 'Target', 'John Lewis', 'Currys', 'Argos'].find(x => x.toLowerCase() === vl);                             if (this.retailerSelect) this.retailerSelect.value = realR;                          } else {                             this.selectedBrands.push(vv);                          }                       }                   });                                      if (this.brandDropdown) {                       const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                       chks.forEach(c => c.checked = this.selectedBrands.includes(c.value));                   }                                      if (r.pr && typeof r.pr === 'string') {                       let prL = r.pr.toLowerCase();                       if (prL.includes('under $')) {                           let m = prL.match(/under \$(\d+)/i);                           if (m && this.customPriceMax && !this.customPriceMax.value) this.customPriceMax.value = m[1];                       }                   }                }                                this.fetchDeals(this.currentQuery);             });           });                      // default to highlighting first           btns[0].classList.add('active');        }async fetchDeals(query, append = false) {          if (!append) {             this.showLoading();             this.deals = [];             this.displayLimit = this.getRowsLimit();          } else {             this.displayLimit += this.getRowsLimit();          }                    try {            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad(append);            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query, append);               } else {                 await this.fetchHawkDeals(query, append);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query, append);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const url = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let dynamicBrandsCounts = {};                    targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                   dynamicBrandsCounts[data.brand] = (dynamicBrandsCounts[data.brand] || 0) + 1;                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || ''                });             });          });                    const airedaleBrandsList = Object.keys(dynamicBrandsCounts).map(b => ({              formatted_value: b,              count: dynamicBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query, append = false) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (append && this.deals.length > 0) {            url.searchParams.append('offset', this.deals.length.toString());          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : (this.getViewMode() === 'savings_squad' ? 'date_desc' : 'discount_desc');          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin-top:8px;">${_div}                ${_div}              ${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)} (${this.airedaleTagCounts[tag] || 0})${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = isSavingsSquadMode ? 'View Deal' : 'Check Price';              if (isSavingsSquadMode) {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                  ${_div}                `;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = `                \x3Cdiv class="tg-df-card-merchant-wrapper">                  \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                ${_div}                \x3Cdiv class="tg-df-card-price-group">                  ${isSavingsSquadMode ? '' : `                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                  `}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description">\x3Cp>${this.escapeHTML(deal.description)}${_p}${_div}` : ''}                      ${_div}                    ${_div}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>${deal.isCheckPrice ? 'Check Price' : 'View Deal'}${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cp style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 12px; line-height: 1.4;">${this.escapeHTML(deal.description)}${_p}` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${priceGroupHtml}                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta ${isSavingsSquadMode ? 'tg-df-cta-savings-squad' : ''}" style="text-decoration: none;">${ctaText}${_a}                  ${_div}                ${_div}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit || ((this.getViewMode() === 'carousel' || this.getViewMode() === 'auto') && displayDeals.length > 0 && displayDeals.length % ((this.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12) === 0)) {            if (this.getViewMode() === 'carousel') {               dealsHtml += `                 \x3Cbutton type="button" class="tg-df-load-more-card tg-df-load-more">                   \x3Csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-bottom: 8px;">\x3Cpath d="M5 12h14">\x3C/path>\x3Cpath d="m12 5 7 7-7 7">\x3C/path>\x3C/svg>                   Load More                 ${_button}               `;            } else {               dealsHtml += `                 \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                   \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer; display: flex; align-items: center;">Load More${_button}                 ${_div}               `;            }          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }                    let gridWrapper = this.grid.parentElement;          if (gridWrapper && gridWrapper.classList.contains('tg-df-grid-wrapper')) {             let rightChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-right');             let leftChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-left');             if (this.getViewMode() === 'carousel') {                 // The observer set up in setupScrollListeners handles visibility.                 if (rightChevron) rightChevron.style.display = 'flex';                 if (leftChevron) leftChevron.style.display = 'none'; // reset correctly             } else {                 if (rightChevron) rightChevron.style.display = 'none';                 if (leftChevron) leftChevron.style.display = 'none';             }          }                    const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', async () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              if (displayDeals.length <= this.displayLimit) {                 loadMoreBtn.innerHTML = `                  <svg class="tg-df-spinner" style="width: 16px; height: 16px; display: inline-block; vertical-align: middle; margin-right: 8px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" d="M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48l2.83-2.83"/></svg>                  Loading...                 `;                 loadMoreBtn.disabled = true;                 await this.fetchDeals(this.currentQuery, true);              } else {                 this.displayLimit += this.getRowsLimit();                 this.render();              }            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            setTimeout(() => {               if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');               document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));            }, 50);          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div> ]]></dc:content>
                                                                                                                                            <link>https://www.tomsguide.com/wellness/running/ive-tested-16-new-carbon-plate-running-shoes-this-year-but-my-favorite-is-still-the-puma-fast-r-3-its-reduced-by-usd100-right-now</link>
                                                                            <description>
                            <![CDATA[ The Puma Fast-R 3 is the fastest racing shoe on the market in my opinion, and a variety of colors are reduced by $100 right now in the Puma sale. ]]>
                                                                                                            </description>
                                                                                                                                <guid isPermaLink="false">DP7qstMbUKihoi92STdrre</guid>
                                                                                                <enclosure url="https://cdn.mos.cms.futurecdn.net/3ckB9sdcGPXS5iUKggvGTG-1920-80.jpg" type="image/jpeg" length="0"></enclosure>
                                                                        <pubDate>Fri, 16 Oct 2026 09:54:14 +0000</pubDate>                                                                                                                                                                                                                                <category><![CDATA[Running]]></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-320-70.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>
                                                                                                                                <cf:isSponsored>false</cf:isSponsored>
                <cf:hasAffiliateLinks>false</cf:hasAffiliateLinks>
                <cf:isPaid>false</cf:isPaid>
                                                                                                                                                                                    <media:content type="image/jpeg" url="https://cdn.mos.cms.futurecdn.net/3ckB9sdcGPXS5iUKggvGTG-1920-80.jpg">
                                                            <media:credit><![CDATA[Future]]></media:credit>
                                                                                                                                                                                                                                    <media:description><![CDATA[Puma Fast-R 3 Savings Squad]]></media:description>                                                            <media:text><![CDATA[Puma Fast-R 3 Savings Squad]]></media:text>
                                <media:title type="plain"><![CDATA[Puma Fast-R 3 Savings Squad]]></media:title>
                                                    </media:content>
                                                    <media:thumbnail url="https://cdn.mos.cms.futurecdn.net/3ckB9sdcGPXS5iUKggvGTG-1920-80.jpg" />
                                                                                                                                                                    <content:encoded >
                            <![CDATA[
                            <article>
                                <p>Carbon plate running shoes have changed the game when it comes to race day, with their propulsive, efficient rides helping runners of all levels break personal records at all distances.</p><p>There are so many great carbon plate racers available it’s hard for a shoe to stand out from the crowd, and more keep coming — I’ve tested 16 new ones in 2026 already.</p><p>However, the Puma Fast-R Nitro Elite 3 <em>does</em> stand out, both for its looks and its performance. It’s still my go-to racer over a year after it came out and <a href="https://us.puma.com/us/en/pd/fast-r-nitro-elite-3-mens-road-running-shoes/312060?" target="_blank" rel="nofollow">you can get it for $199 in the Puma sale right now</a>, a hefty $100 saving.</p><div class="product"><a data-dimension112="cf2387ee-c93e-11f1-8dac-9b80399f2383" data-action="Deal Block" data-label="Fast-R Nitro Elite 3" data-dimension48="Fast-R Nitro Elite 3" data-dimension25="$199" href="https://us.puma.com/us/en/pd/fast-r-nitro-elite-3-mens-road-running-shoes/312060?" target="_blank" rel="nofollow"><figure class="van-image-figure "  ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:750px;"><p class="vanilla-image-block" style="padding-top:100.00%;"><img id="suWtb7xw9PohDdD7uw25NQ" name="Puma Fast-R Nitro Elite 3" caption="" alt="" src="https://cdn.mos.cms.futurecdn.net/suWtb7xw9PohDdD7uw25NQ-1920-80.png" mos="" align="middle" fullscreen="" width="750" height="750" attribution="" endorsement="" credit="" class="" /></p></div></div></figure></a><p><strong><a href="https://us.puma.com/us/en/pd/fast-r-nitro-elite-3-mens-road-running-shoes/312060?" target="_blank" rel="nofollow" data-dimension112="cf2387ee-c93e-11f1-8dac-9b80399f2383" data-action="Deal Block" data-label="Fast-R Nitro Elite 3" data-dimension48="Fast-R Nitro Elite 3" data-dimension25="$199">Fast-R Nitro Elite 3: was $300 now $199</a></strong><br />All colors of the Puma Fast-R 3 are reduced to $199 in the Puma sale, and there is a wide range of sizes still available. It's still not exactly cheap, but that's a great price for what I think is the best racing shoe on the market right now.<a class="view-deal button" href="https://us.puma.com/us/en/pd/fast-r-nitro-elite-3-mens-road-running-shoes/312060?" target="_blank" rel="nofollow" data-dimension112="cf2387ee-c93e-11f1-8dac-9b80399f2383" data-action="Deal Block" data-label="Fast-R Nitro Elite 3" data-dimension48="Fast-R Nitro Elite 3" data-dimension25="$199">View Deal</a></p></div><p>I was wowed by the Puma Fast-R 3 from the moment I first tested it. I ran a 15-minute 5K parkrun in it out of the box, then used it to run a 2:26 at the London Marathon a week later.</p><p>Since then I’ve used it to run my 5-mile PR and many other races and hard training sessions, and I’m on my second pair of the shoe.</p><figure class="van-image-figure  inline-layout" data-bordeaux-image-check="" ><div class='image-full-width-wrapper'><div class='image-widthsetter' style="max-width:4032px;"><p class="vanilla-image-block" style="padding-top:56.25%;"><img id="H7QtF35Z9D26sCbn5aJhMV" name="Puma Fast-R Nitro Elite 3" alt="Puma Fast-R Nitro Elite 3" src="https://cdn.mos.cms.futurecdn.net/H7QtF35Z9D26sCbn5aJhMV-1920-80.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>Even in the crowded carbon market the Puma Fast-R 3 has a unique ride thanks to the extended carbon plate and aggressively rockered geometry that helps you to keep pushing and hold your goal race pace all the way to the finish line.</p><p>I’ve spent the last few months training for the Frankfurt Marathon when I’ll be wearing the Fast-R 3 again to try and set a new PR. </p><div><blockquote><p>I’ve spent the last few months training for the Frankfurt Marathon when I’ll be wearing the Fast-R 3 again to try and set a new PR. </p></blockquote></div><p>It’s an expensive shoe and I wouldn't expect to get more than 200-300 miles out of a pair before they’re past their best, but on race day I just want the fastest shoe on my feet.</p><p>I’ve not seen big discounts crop up on the Fast-R 3 all that often since it came out last year, so the $100 saving you can get in the Puma sale right now is exceptional.</p><p>It is a shame, however, that it’s not currently included in the <a href="https://us.puma.com/us/en/sale/all-sale" target="_blank" rel="nofollow">STOCKUP promotion on the Puma site</a>, where you get an extra 20% off for buying two sale items, 30% for three, and 40% for four.</p><p>That said, if you want to add some running apparel and accessories to your basket alongside the Fast-R 3, you can stock up on socks, tees and shorts in the sale for less.</p><div class="vizualizer-embed"><div class="tg-df-widget-host" data-widget-config="?search=Home+Tech&amp;view_mode=carousel&amp;widget_title=Top+Deals+Handpicked+by+Our+Editors&amp;widget_subtitle=Discover+the+best+discounts+currently+available%2C+curated+daily+by+the+Tom%27s+Guide+Savings+Squad.&amp;bg_color=light_blue" data-vizualizer-embed="true"></div>    <script>    /**     * Tom's Guide Deals Finder - Vanilla JS Encapsulated Engine     */    (function() {      // --- Freyr Analytics Adapter ---      function initAnalytics() {        window.dataLayer = window.dataLayer || [];        window.googletag = window.googletag || {};        window.googletag.cmd = window.googletag.cmd || [];        window.hawk = window.hawk || { analytics: { freyr: [] } };        window.hawk.analytics = window.hawk.analytics || { freyr: [] };        window.hawk.analytics.freyr = window.hawk.analytics.freyr || [];        window.freyr = window.freyr || { cmd: [] };        const scriptSrc = 'https://freyr.futurecdn.net/freyr.js';        const hostname = typeof window !== 'undefined' ? window.location.hostname : '';        const isTestEnv = typeof window.navigator !== 'undefined' && (window.navigator.webdriver || window.navigator.userAgent.includes('Headless'));        const shouldSendRealAnalytics = !isTestEnv && hostname && hostname !== 'localhost' && hostname !== '127.0.0.1' && !hostname.includes('run.app');        if (shouldSendRealAnalytics && !document.querySelector(`script[src="${scriptSrc}"]`)) {          const script = document.createElement('script');          script.src = scriptSrc;          script.async = true;          document.head.appendChild(script);        }      }      function storeEventForDebug(name, data) {        if (!window.hawk || !window.hawk.analytics || !window.hawk.analytics.freyr) return;        window.hawk.analytics.freyr.push({ name, data });        try {          if (typeof window !== 'undefined' && window.localStorage) {            window.localStorage.setItem("hawk", JSON.stringify(window.hawk));          }        } catch (e) {          // Ignore storage issues        }        try {          window.dispatchEvent(new CustomEvent("hawk-analytics-update"));        } catch (e) {}      }      function sendToFreyr(eventName, data) {        if (typeof window === 'undefined') return;        window.freyr = window.freyr || { cmd: [] };        window.freyr.cmd.push(() => {          if (window.freyr && window.freyr.pushAndUpdate) {            window.freyr.pushAndUpdate(eventName, data);          }        });      }      function sendEvent(event, skip = false) {        try {          storeEventForDebug(event.name, event.data);          if (!skip) {            sendToFreyr(event.name, event.data);          }        } catch (e) {          // Ensure tracking errors don't surface to the user        }      }      function getCookie(name) {        try {          const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));          return match ? match[2] : null;        } catch (e) {          return null;        }      }      function normalizeCurrency(symbol) {        const map = {          '£': 'GBP',          '$': 'USD',          'A$': 'AUD',          'CA$': 'CAD',          '€': 'EUR'        };        return map[symbol] || symbol;      }      function trackElementInteraction(props) {        sendEvent({          name: 'elementInteraction',          data: {            element: {              action: props.action || "click",              id: props.id || undefined,              class: props.class || undefined,              name: props.name || undefined,              text: props.text || undefined,              label: props.label || undefined,              container: props.container || undefined,              url: props.url || undefined,              articleId: props.articleId || undefined            }          }        });      }      function generateRevenueId(url, productName, merchantName, modelId) {        const str = `${window.location.href}|${productName}|${merchantName}|${modelId || ''}|${new Date().toDateString()}|tomsguide`;        let hash = 0;        for (let i = 0; i < str.length; i++) {          const char = str.charCodeAt(i);          hash = ((hash << 5) - hash) + char;          hash = hash & hash;        }        let numericStr = Math.abs(hash).toString();        while (numericStr.length < 19) {          numericStr += Math.floor(Math.random() * 10).toString();        }        return numericStr.substring(0, 19);      }      function rewriteAffiliateLink(url, territory, revenueId) {        if (!url) return url;        const t = (territory || 'gb').toLowerCase();        return url.replace(/hawk-custom-tracking/g, `tomsguide-${t}-${revenueId}`);      }      function trackHawkEvent(params) {        const { clickType, widgetId, productCategoryName, product, productsArray, zeroBasedProductIndexOrNull, totalDealsOrProducts, areaClicked, merchant, revenueId, isoCurrencyCode, queryName, widgetTypeName } = params;        const data = {          event: "hawkEvent",          category: "Affiliates",          affiliate: {            action: {              type: clickType,              id: widgetId,              event: clickType === "appeared" ? "viewed" : "Click from",              timestamp: Date.now()            },            component: {              flag: "Editor",              product: productCategoryName || "deals",              category: `Signal Deal Finder ${widgetTypeName || "Carousel"} widget`,              type: clickType === "appeared" ? "review" : "signal product",              label: queryName || (product ? (product.name || "") : ""),              index: zeroBasedProductIndexOrNull === null || zeroBasedProductIndexOrNull === undefined ? -1 : zeroBasedProductIndexOrNull,              linkCount: totalDealsOrProducts || 0,              blockLayout: "",              areaClicked: areaClicked || ""            }          },          products: productsArray || (product && merchant ? [            {              product: {                primary: {                  id: product.id || product.matchId || null,                  name: product.name,                  type: "deal",                  price: product.price,                  previousPrice: product.previousPrice || null,                  currency: isoCurrencyCode || "USD",                  preorder: false,                  labels: [],                  link: product.link,                  originalLink: product.originalLink || null,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: null,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: product.globalId || null,                  inStock: product.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: isoCurrencyCode || "USD"                }              },              merchant: {                id: merchant.id || null,                name: merchant.name,                url: merchant.url || null,                network: merchant.network || null              },              model: {                id: product.modelId || null,                brand: product.brand || null,                name: product.name,                parent: product.parent || null              }            }          ] : []),          reviews: [],          _clear: true,          "gtm.uniqueEventId": Date.now() % 10000        };        sendEvent({ name: 'hawkEvent', data });      }      function trackDealClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card" });      }      function trackViewSimilarClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Product Card View Similar" });      }      function trackPriceComparisonClick(params) {        trackHawkEvent({ ...params, clickType: "retailer", areaClicked: "Signal Price Comparison" });      }      function trackReviewClick(params) {        trackHawkEvent({ ...params, clickType: "review", areaClicked: "Signal Product Card Review Link" });      }      function trackShare(params) {        trackHawkEvent({ ...params, clickType: "share", areaClicked: "Signal Product Card Share" });      }      function trackDealsAppeared(widgetId, deals, revenueId, currency, queryName, widgetTypeName) {         if (!deals || deals.length === 0) return;                  const productsArray = deals.slice(0, 50).map((deal) => {            let voucherPct = null;            let rawPrice = parseFloat(deal.rawPrice) || parseFloat(deal.price) || null;            let rawMsrp = parseFloat(deal.rawMsrp) || parseFloat(deal.msrp) || null;            if (rawMsrp > rawPrice && rawPrice > 0) {              voucherPct = Math.round((1 - (rawPrice / rawMsrp)) * 100);            }            let numId = null;            if (deal.externalProductId && !isNaN(parseInt(deal.externalProductId))) {              numId = parseInt(deal.externalProductId);            } else if (deal.id && !isNaN(parseInt(deal.id))) {              numId = parseInt(deal.id);            } else {              numId = deal.matchId || null;            }            return {              product: {                primary: {                  id: numId,                  name: deal.productName || deal.title || "",                  type: "deal",                  price: rawPrice,                  previousPrice: rawMsrp,                  currency: currency || 'USD',                  preorder: false,                  labels: deal.modelBrand || deal.brand ? [                     { type: "brand", value: deal.modelBrand || deal.brand }                  ] : [],                  link: deal.url,                  originalLink: deal.url,                  revenueId: revenueId || null,                  startTime: null,                  endTime: null,                  voucherCode: null,                  voucherAudience: null,                  voucherPercentageSaving: voucherPct,                  voucherMoneySaving: null,                  voucherType: null,                  offerExclusive: false,                  offerScope: null,                  globalId: deal.productKey || null,                  inStock: deal.inStock !== false,                  contractProvider: null,                  contractMinutes: null,                  contractTexts: null,                  contractData: null,                  contractLength: null,                  contractMonthlyPrice: null,                  contractCurrency: currency || 'USD'                }              },              merchant: {                id: deal.merchantId ? parseInt(deal.merchantId) : null,                name: deal.merchant || "Retailer",                url: deal.merchantUrl || null,                network: deal.merchantNetwork || null              },              model: {                id: deal.modelId ? parseInt(deal.modelId) : null,                brand: deal.modelBrand || deal.brand || null,                name: deal.productName || deal.title || "",                parent: deal.modelParent || null              }            };         });                  trackHawkEvent({             clickType: "appeared",             widgetId: widgetId,             productCategoryName: "deals",             zeroBasedProductIndexOrNull: null,             totalDealsOrProducts: deals.length,             productsArray: productsArray,             queryName: queryName,             widgetTypeName: widgetTypeName         });      }      // 1. Setup Shadow DOM Sandbox      const currentScript = document.currentScript;      let hostContainer = null;      let template = null;            if (currentScript) {        let prev = currentScript.previousElementSibling;        while (prev) {          if (prev.tagName === 'TEMPLATE' && prev.classList.contains('tg-df-widget-template')) {            template = prev;          } else if (prev.tagName === 'DIV' && prev.classList.contains('tg-df-widget-host') && !prev.hasAttribute('data-initialized')) {            hostContainer = prev;            break;          }          prev = prev.previousElementSibling;        }      }            // Fallbacks in case script is deferred      if (!hostContainer) {        const hosts = document.querySelectorAll('.tg-df-widget-host:not([data-initialized])');        if (hosts.length > 0) hostContainer = hosts[0];      }            // Safely embedded template for CMS environments      const rawTemplate = `  \x3Cstyle>    /* --- Shadow DOM Base Reset --- */    *, *::before, *::after {      box-sizing: border-box;    }    img, picture, svg, video {      max-width: 100%;      height: auto;      display: block;    }    /*       1. Scoped CSS for Tom's Guide Deals Widget       All classes are prefixed with \`tg-df-\` to prevent CMS style leakage.    */    .tg-df-container {      container-type: inline-size;      container-name: tg-df;      --tg-df-blue: #1F69FF;      --tg-df-blue-hover: #004d8c;      --tg-df-text: #222222;      --tg-df-text-muted: #555555;      --tg-df-bg: #ffffff;      --tg-df-bg-secondary: #f4f4f4;      --tg-df-border: #e2e8f0;      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;      color: var(--tg-df-text);      background-color: transparent;       width: 100%;      max-width: 1200px;      margin: 0 auto;      padding-bottom: 24px;    }    .tg-df-container *, .tg-df-container *::before, .tg-df-container *::after {      margin: 0;      padding: 0;      box-sizing: border-box;    }    .tg-df-container img {      border: none;      margin: 0;      padding: 0;    }    .tg-df-container a {      text-decoration: none;      color: inherit;    }    /*       2. Search & Filter Bar    */    .tg-df-controls {      display: flex;      flex-direction: column;      align-items: center;      gap: 20px;      margin-bottom: 32px;      width: 100%;    }    .tg-df-top-bar {      display: flex;      width: 100%;      max-width: 760px;      gap: 12px;      align-items: center;    }    .tg-df-search-wrapper {      position: relative;      flex: 1;      width: 100%;      box-shadow: 0 8px 24px rgba(0,0,0,0.06);      border-radius: 40px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      z-index: 100;    }    .tg-df-autocomplete-dropdown {      position: absolute;      top: calc(100% + 4px);      left: 0;      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      max-height: 300px;      overflow-y: auto;      z-index: 200;      display: none;    }    .tg-df-autocomplete-dropdown.active {      display: block;    }    .tg-df-autocomplete-item {      padding: 12px 24px;      cursor: pointer;      font-size: 14px;      color: var(--tg-df-text);      transition: background 0.1s ease;    }    .tg-df-autocomplete-item:hover {      background: var(--tg-df-bg-secondary);    }    .tg-df-search-input {      width: 100%;      padding: 16px 64px 16px 24px;      font-size: 16px;      border: 2px solid transparent;      border-radius: 40px;      outline: none;      transition: border-color 0.2s ease, box-shadow 0.2s ease;      color: var(--tg-df-text);      background: transparent;    }    .tg-df-search-input:focus {      border-color: transparent;      box-shadow: 0 0 0 3px rgba(0, 108, 196, 0.15);    }    .tg-df-search-input::placeholder {      color: #999999;    }        .tg-df-search-btn {      position: absolute;      right: 8px;      top: 50%;      transform: translateY(-50%);      width: 40px;      height: 40px;      border-radius: 50%;      background: #222;      border: none;      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: background 0.2s ease;    }        .tg-df-search-btn:hover {      background: #000;    }    .tg-df-search-icon {      width: 16px;      height: 16px;      fill: #fff;    }    .tg-df-settings-wrapper {      position: relative;    }        .tg-df-settings-btn {      width: 48px;      height: 48px;      border-radius: 50%;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      box-shadow: 0 4px 12px rgba(0,0,0,0.04);      display: flex;      align-items: center;      justify-content: center;      cursor: pointer;      transition: all 0.2s ease;      color: var(--tg-df-text-muted);      flex-shrink: 0;    }    .tg-df-settings-btn:hover {      background: var(--tg-df-bg-secondary);      border-color: #0000ff;      color: var(--tg-df-text);    }    .tg-df-settings-btn svg {      width: 24px;      height: 24px;      fill: currentColor;    }    .tg-df-settings-dropdown {      position: absolute;      top: calc(100% + 8px);      right: 0;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 12px;      box-shadow: 0 8px 32px rgba(0,0,0,0.12);      width: 280px;      padding: 20px;      display: none;      z-index: 100;      flex-direction: column;      gap: 20px;    }    .tg-df-settings-dropdown.active {      display: flex;    }        .tg-df-settings-dropdown-backdrop {      display: none;      position: fixed;      inset: 0;      z-index: 99;    }        .tg-df-settings-dropdown-backdrop.active {      display: block;    }    .tg-df-setting-item {      display: flex;      flex-direction: column;      gap: 10px;    }    .tg-df-setting-label {      font-size: 11px;      font-weight: 700;      color: var(--tg-df-text-muted);      text-transform: uppercase;      letter-spacing: 0.5px;    }        .tg-df-region-select {        padding: 10px 12px;        border-radius: 8px;        border: 1px solid var(--tg-df-border);        font-size: 15px;        outline: none;        background: var(--tg-df-bg-secondary);        color: var(--tg-df-text);        cursor: pointer;        width: 100%;    }    .tg-df-toggle {        position: relative;        display: inline-block;        width: 44px;        height: 24px;        flex-shrink: 0;    }    .tg-df-toggle input {        opacity: 0;        width: 0;        height: 0;    }    .tg-df-slider {        position: absolute;        cursor: pointer;        top: 0; left: 0; right: 0; bottom: 0;        background-color: #ccc;        transition: .2s;        border-radius: 24px;    }    .tg-df-slider:before {        position: absolute;        content: "";        height: 18px;        width: 18px;        left: 3px;        bottom: 3px;        background-color: white;        transition: .2s;        border-radius: 50%;    }    .tg-df-toggle input:checked + .tg-df-slider {        background-color: #1F69FF;    }    .tg-df-toggle input:checked + .tg-df-slider:before {        transform: translateX(20px);    }    .tg-df-dl-row {        flex-direction: row;        align-items: center;        justify-content: space-between;    }    .tg-df-dl-row-text {        font-size: 14px;        font-weight: 600;        color: var(--tg-df-text);    }    .tg-df-dl-row-subtext {        font-size: 12px;        font-weight: 400;        line-height: 1.3;        color: var(--tg-df-text-muted);        margin-top: 4px;        display: block;    }    .tg-df-filters {      display: flex;      gap: 12px;      justify-content: center;      flex-wrap: wrap;    }    .tg-df-sort-wrapper {      position: relative;      display: flex;      align-items: center;    }        .tg-df-sort-icon {      position: absolute;      left: 14px;      width: 14px;      height: 14px;      fill: var(--tg-df-text-muted);      pointer-events: none;    }    .tg-df-sort-select, .tg-df-filter-select {      padding: 10px 36px 10px 38px;      font-size: 14px;      border: 1px solid var(--tg-df-border);      border-radius: 100px;      outline: none;      appearance: none;      background-color: var(--tg-df-bg-secondary);      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%23555555' d='M6 8L1 3h10z'/%3E%3C/svg%3E");      background-repeat: no-repeat;      background-position: right 14px center;      color: var(--tg-df-text);      cursor: pointer;      font-weight: 500;      transition: all 0.2s ease;    }        .tg-df-price-input::-webkit-outer-spin-button,    .tg-df-price-input::-webkit-inner-spin-button {      -webkit-appearance: none;      margin: 0;    }    .tg-df-price-input {      -moz-appearance: textfield;    }    .tg-df-sort-select:hover, .tg-df-filter-select:hover {      background-color: #e2e8f0;    }    .tg-df-multiselect-container {      position: relative;    }        .tg-df-multiselect-trigger {      display: block;      background: #fff;      user-select: none;      width: 100%;      overflow: hidden;      white-space: nowrap;      text-overflow: ellipsis;    }        .tg-df-multiselect-dropdown {      display: none;      position: absolute;      top: calc(100% + 4px);      left: 0;      width: 100%;      min-width: 220px;      max-height: 300px;      overflow-y: auto;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);      z-index: 100;      padding: 8px 0;    }    .tg-df-multiselect-dropdown.active {      display: block;    }    .tg-df-ms-option {      padding: 8px 16px;      display: flex;      align-items: center;      gap: 8px;      cursor: pointer;      font-size: 14px;    }    .tg-df-ms-option:hover {      background-color: var(--tg-df-bg-secondary);    }        .tg-df-ms-option input {      cursor: pointer;      accent-color: #1f69ff;    }    .tg-df-sort-select:focus, .tg-df-filter-select:focus {      border-color: #0000ff;      box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.2);      background-color: var(--tg-df-bg);    }    /*       3. Deal Grid Layout    */    .tg-df-grid.tg-df-grid-auto {      padding-top: 24px;    }    .tg-df-grid, .tg-df-grid.layout-grid {      display: grid;      grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));      gap: 10px;    }    .tg-df-grid.layout-row {      grid-template-columns: 1fr;      gap: 16px;    }        .tg-df-grid.layout-row .tg-df-card {      flex-direction: row;      align-items: stretch;      height: auto;      box-shadow: none;      border-bottom: 1px solid var(--tg-df-border);    }    .tg-df-grid.layout-row .tg-df-card:hover {      box-shadow: none;    }    .tg-df-grid.layout-row .tg-df-card-image-box {      width: 140px;      min-width: 140px;      aspect-ratio: 3/4;      border-right: none;      padding: 16px 16px 16px 32px;    }    .tg-df-grid.layout-row .tg-df-card-body {      padding: 16px;      justify-content: space-between;    }    .tg-df-grid.layout-row .tg-df-card-title {      font-size: 15px;      margin-bottom: 16px;    }    .tg-df-grid.layout-row .tg-df-card-stars { margin-bottom: 8px; }    .tg-df-grid.layout-row .tg-df-card-footer {      flex-direction: column;      align-items: flex-start;      gap: 0;    }    .tg-df-grid.layout-row .tg-df-card-merchant-pill {      margin-bottom: 4px;    }    .tg-df-grid.layout-row .tg-df-card-price-group {      margin-bottom: 8px;    }    .tg-df-grid.layout-row .tg-df-price-group {      width: auto;    }    .tg-df-grid.layout-row .tg-df-card-cta {      width: 100%;      max-width: 200px;      padding: 10px 24px;      font-size: 13px;      flex-shrink: 0;      text-align: center;      justify-content: center;    }    /*       4. Deal Card Design    */    .tg-df-card {      position: relative;      display: flex;      flex-direction: column;      background-color: #ffffff;      border-radius: 0;      overflow: hidden;      transition: transform 0.2s ease, box-shadow 0.2s ease;      text-decoration: none;      color: inherit;      height: 100%;      box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);      border: 1px solid var(--tg-df-border);    }    .tg-df-card:hover {      box-shadow: 0 0 24px rgba(0, 0, 0, 0.12);    }    .tg-df-card-image-box {      width: 100%;      aspect-ratio: 3/4;      background-color: #f8f8f8;      display: flex;      align-items: center;      justify-content: center;      position: relative;      overflow: hidden;      padding: 32px;      flex: 0 0 auto;    }    .tg-df-card-image {      max-width: 100%;      max-height: 100%;      width: auto;      height: auto;      object-fit: contain;      mix-blend-mode: multiply; /* Helps white background images blend into secondary bg */      transition: transform 0.3s ease;    }    .tg-df-card:hover .tg-df-card-image {      transform: scale(1.05); /* Zoom in on hover */    }    .tg-df-card-discount-badge {      position: absolute;      top: 12px;      left: 12px;      background: #dc2626; /* Red */      color: #ffffff;      padding: 6px 8px;      font-size: 11px;      font-weight: 500;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      z-index: 10;    }        .tg-df-card-merchant-pill {      display: block;      padding: 0;      font-size: 11px;      font-weight: 600;      text-transform: uppercase;      letter-spacing: 0.5px;      border-radius: 0;      color: var(--tg-df-text-muted);      margin-bottom: 8px;      white-space: nowrap;      overflow: hidden;      text-overflow: ellipsis;    }    .tg-df-card-body {      padding: 16px;      display: flex;      flex-direction: column;      flex-grow: 1;      min-width: 0;    }    .tg-df-card-badges {      display: flex;      flex-wrap: wrap;      gap: 6px;      margin-bottom: 8px;    }    .tg-df-tag {      display: inline-flex;      align-items: center;      padding: 4px 6px;      font-size: 11px;      font-weight: 700;      text-transform: uppercase;      border-radius: 4px;      gap: 4px;    }    .tg-df-tag-prime {      background-color: #00A8E1;      color: #fff;    }    .tg-df-tag-coupons {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-coupons:hover {      background-color: #e2e8f0;    }        .tg-df-tag-outline {      background-color: #f1f5f9;      color: #334155;      border: 1px solid #cbd5e1;      cursor: pointer;      transition: background-color 0.2s;    }    .tg-df-tag-outline:hover {      background-color: #e2e8f0;    }        @keyframes tg-df-spin {      0% { transform: rotate(0deg); }      100% { transform: rotate(360deg); }    }    .tg-df-coupon-spinner {      border: 2px solid #e2e8f0;      border-top: 2px solid #3b82f6;      border-radius: 50%;      width: 14px;      height: 14px;      animation: tg-df-spin 1s linear infinite;      margin: 4px 8px;      display: inline-block;    }        /* Vouchers Modal */    .tg-df-modal-backdrop {      position: fixed;      top: 0; left: 0; right: 0; bottom: 0;      background: rgba(0,0,0,0.5);      z-index: 10000;      display: flex;      align-items: center;      justify-content: center;      opacity: 0;      pointer-events: none;      transition: opacity 0.3s;    }    .tg-df-modal-backdrop.active {      opacity: 1;      pointer-events: auto;    }    .tg-df-modal {      background: #fff;      border-radius: 12px;      width: 90%;      max-width: 400px;      max-height: 80vh;      display: flex;      flex-direction: column;      box-shadow: 0 10px 40px rgba(0,0,0,0.2);      transform: translateY(20px);      transition: transform 0.3s;    }    .tg-df-modal-backdrop.active .tg-df-modal {      transform: translateY(0);    }    .tg-df-modal-header {      padding: 16px;      border-bottom: 1px solid #e2e8f0;      display: flex;      align-items: center;      justify-content: space-between;    }    .tg-df-modal-title {      font-size: 16px;      font-weight: 600;      margin: 0;    }    .tg-df-modal-close {      background: none;      border: none;      cursor: pointer;      padding: 4px;      color: #64748b;    }    .tg-df-modal-body {      padding: 16px;      overflow-y: auto;    }    .tg-df-voucher-item {      padding: 12px;      border: 1px dashed #cbd5e1;      border-radius: 8px;      margin-bottom: 10px;      background: #f8fafc;      display: flex;      align-items: center;      gap: 12px;      text-decoration: none;      color: inherit;      transition: background-color 0.2s, border-color 0.2s;    }    .tg-df-voucher-item:hover {      background: #f1f5f9;      border-color: #94a3b8;    }    .tg-df-voucher-item:last-child {      margin-bottom: 0;    }    .tg-df-voucher-logo {      width: 48px;      height: 48px;      object-fit: contain;      border-radius: 4px;      background: #fff;      border: 1px solid #e2e8f0;      flex-shrink: 0;    }    .tg-df-voucher-content {      flex: 1;      min-width: 0;    }    .tg-df-voucher-title {      font-size: 14px;      font-weight: 600;      margin: 0 0 4px 0;      line-height: 1.3;      color: #0f172a;    }    .tg-df-voucher-expiry {      font-size: 12px;      color: #64748b;      display: flex;      align-items: center;      gap: 4px;      margin-top: 6px;    }    .tg-df-voucher-code {      display: inline-flex;      align-items: center;      background: #f1f5f9;      border: 1px dashed #cbd5e1;      padding: 6px 10px;      font-family: monospace;      font-weight: 700;      font-size: 14px;      color: #0f172a;      border-radius: 4px;      margin-top: 8px;      cursor: pointer;      transition: all 0.2s ease;    }    .tg-df-voucher-code:hover {      background: #e2e8f0;      border-color: #94a3b8;    }    .tg-df-voucher-code.copied {      background: #ecfdf5;      border-color: #10b981;      color: #10b981;    }    .tg-df-voucher-cta {      display: inline-block;      margin-top: 8px;      font-size: 13px;      font-weight: 600;      color: #2563eb;      text-decoration: none;    }    .tg-df-card-title {      font-size: 15px;      font-weight: 400;      line-height: 1.4;      margin: 0 0 12px 0;      color: var(--tg-df-text);      display: -webkit-box;      -webkit-line-clamp: 2;      -webkit-box-orient: vertical;      overflow: hidden;    }    .tg-df-card-footer {      margin-top: auto;      display: flex;      flex-direction: column;      width: 100%;    }    .tg-df-card-price-group {      display: flex;      flex-direction: row;      align-items: center;      gap: 8px;      margin-bottom: 12px;    }    .tg-df-card-price {      font-size: 16px;      font-weight: 700;      color: #dc2626; /* Red price */      line-height: 1;    }        .tg-df-card-msrp {      font-size: 13px;      color: var(--tg-df-text-muted);      text-decoration: line-through;    }    .tg-df-container .tg-df-card-cta {      display: flex;      align-items: center;      justify-content: center;      width: 100%;      box-sizing: border-box;      background-color: #1f69ff;      color: #ffffff;      font-size: 12px;      font-weight: 700;      text-transform: uppercase;      letter-spacing: 0.5px;      padding: 12px 16px;      border-radius: 0;      border: none;      cursor: pointer;      transition: background-color 0.2s ease;    }    .tg-df-card:hover .tg-df-card-cta,    .tg-df-card-cta:hover {      background-color: #1555cc;    }    .tg-df-container .tg-df-card-cta.tg-df-cta-savings-squad {      background-color: #3c8d0d;    }    .tg-df-card:hover .tg-df-card-cta.tg-df-cta-savings-squad,    .tg-df-card-cta.tg-df-cta-savings-squad:hover {      background-color: #2b6509;    }    /*       5. State & Skeleton Styles    */    .tg-df-message {      grid-column: 1 / -1;      text-align: center;      padding: 48px 24px;      color: var(--tg-df-text-muted);      font-size: 16px;      background: var(--tg-df-bg);      border: 1px solid var(--tg-df-border);      border-radius: 8px;    }    @keyframes tg-df-shimmer {      0% { background-position: -200% 0; }      100% { background-position: 200% 0; }    }    .tg-df-skeleton {      background: linear-gradient(90deg, var(--tg-df-bg-secondary) 25%, #e2e8f0 50%, var(--tg-df-bg-secondary) 75%);      background-size: 200% 100%;      animation: tg-df-shimmer 1.5s infinite;      border-radius: 4px;    }    .tg-df-skeleton-img {      width: 100%;      height: 100%;      position: absolute;      top: 0; left: 0;    }        .tg-df-skeleton-text {      height: 16px;      margin-bottom: 8px;      width: 100%;    }    .tg-df-skeleton-text.short { width: 40%; }    .tg-df-skeleton-text.title { height: 20px; margin-bottom: 16px; }    /* Editor Floating Bar & Elements */    .tg-df-editor-bar {      position: sticky;      top: 0;      z-index: 1000;      background: #111827;      color: #fff;      padding: 12px 16px;      border-radius: 8px;      margin-bottom: 16px;      display: flex;      align-items: center;      justify-content: space-between;      box-shadow: 0 4px 12px rgba(0,0,0,0.15);    }    .tg-df-editor-bar-text {      font-weight: 600;      font-size: 14px;    }    .tg-df-editor-copy-btn {      background: #10b981;      color: #fff;      padding: 6px 16px;      border: none;      border-radius: 4px;      font-weight: 600;      cursor: pointer;      display: flex;      align-items: center;      font-size: 13px;    }    .tg-df-editor-copy-btn:hover { background: #059669; }        .tg-df-deal-checkbox {      position: absolute;      top: 12px;      right: 12px;      z-index: 10;      width: 20px;      height: 20px;      cursor: pointer;      pointer-events: auto;    }    /*       6. Mobile List View (Stacks into a cleaner horizontal row/list)    */    @container tg-df (max-width: 599px) {      .tg-df-controls {        padding: 0 16px;      }            .tg-df-top-bar {        width: 100%;      }            .tg-df-settings-dropdown {        position: fixed;        top: auto;        bottom: 0;        left: 0;        right: 0;        width: 100%;        border-radius: 20px 20px 0 0;        padding: 24px;        box-shadow: 0 -8px 32px rgba(0,0,0,0.15);        z-index: 1000;        border: none;        border-top: 1px solid var(--tg-df-border);      }            .tg-df-settings-dropdown-backdrop.active {        background: rgba(0,0,0,0.4);      }            .tg-df-search-wrapper {        box-shadow: 0 0 16px rgba(0,0,0,0.08);      }            .tg-df-filters {        width: calc(100% + 32px);        margin: 0 -16px;        padding: 0 16px 4px 16px;        display: flex;        justify-content: flex-start;        gap: 8px;        flex-wrap: nowrap;        overflow-x: auto;        -webkit-overflow-scrolling: touch;        scrollbar-width: none;      }      .tg-df-filters::after {        content: "";        display: block;        flex: 0 0 8px;      }      .tg-df-filters::-webkit-scrollbar {        display: none;      }            .tg-df-sort-wrapper {        flex: 0 0 max(42%, 130px);        min-width: 0;      }      .tg-df-sort-wrapper.tg-df-price-range-wrapper {        flex: 0 0 auto;        min-width: max-content;      }            .tg-df-sort-select, .tg-df-filter-select {        width: 100%;        text-align: left;        padding: 10px 24px 10px 32px;        background-position: right 8px center;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;      }      .tg-df-sort-icon {        left: 10px;      }      .tg-df-grid:not(.layout-grid):not(.layout-row),      .tg-df-grid.layout-row {        grid-template-columns: 1fr;        gap: 16px;      }            .tg-df-grid.tg-df-grid-auto {        padding-top: 24px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card,      .tg-df-grid.layout-row .tg-df-card {        flex-direction: row;        align-items: stretch;        height: auto;        box-shadow: none; /* simple line on mobile if preferred, or keep */        border-bottom: 1px solid var(--tg-df-border);      }      .tg-df-grid.tg-df-grid-auto .tg-df-card:hover,      .tg-df-grid.layout-row .tg-df-card:hover {        box-shadow: none;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-image-box,      .tg-df-grid.layout-row .tg-df-card-image-box {        width: 120px;        min-width: 120px;        aspect-ratio: 3/4;        border-right: none;        padding: 12px;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-body,      .tg-df-grid.layout-row .tg-df-card-body {        padding: 12px;        justify-content: space-between;      }      .tg-df-grid.tg-df-grid-auto .tg-df-card-title,      .tg-df-grid.layout-row .tg-df-card-title {        font-size: 14px;        margin-bottom: 12px;        -webkit-line-clamp: 3;      }      /* Single column mobile grid override */      .tg-df-grid.layout-grid {        grid-template-columns: 1fr;        gap: 16px;      }      .tg-df-grid.layout-grid .tg-df-card-image-box {        padding: 12px;      }      .tg-df-grid.layout-grid .tg-df-card-body {        padding: 10px;      }      .tg-df-grid.layout-grid .tg-df-card-title {        font-size: 13px;        -webkit-line-clamp: 3;        margin-bottom: 8px;      }      .tg-df-grid.layout-grid .tg-df-card-price {        font-size: 14px;      }            .tg-df-card-footer {        flex-direction: column;        align-items: stretch;        gap: 0;        width: 100%;        min-width: 0;      }      .tg-df-card-merchant-pill {        margin-bottom: 4px;      }      .tg-df-card-price-group {        flex: 1 1 auto;        margin-bottom: 8px;      }      .tg-df-card-price {        font-size: 16px;      }      .tg-df-card-msrp {        display: block;       }      .tg-df-grid.layout-row .tg-df-card-cta,      .tg-df-container .tg-df-card-cta {        width: 100%;        max-width: none;        min-width: 0;        box-sizing: border-box;        padding: 8px 16px;        font-size: 12px;        flex: 0 0 auto;        text-align: center;        white-space: normal;        line-height: 1.2;      }    }    .tg-df-container.is-carousel {      min-height: 760px;      background-color: #E7F0FF;      padding: 0 0 24px 0;      border-radius: 24px;    }    .tg-df-container.is-carousel.hide-header-details {      min-height: 480px;    }    /*       7. Carousel View Mode    */    .tg-df-container .tg-df-carousel-host {      /* Layout is now handled by container wrapper */    }    .tg-df-container .tg-df-carousel-eyebrow {      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      padding: 24px 16px 0 16px;      display: none;    }    .tg-df-container .tg-df-carousel-query-title {      color: #011535;      font-size: 28px;      font-weight: 600;      padding: 0 16px 24px 16px;      line-height: 1.2;      display: none;    }    .tg-df-container .tg-df-carousel-blue-box {      background-color: transparent;      border-radius: 0;      padding: 24px 24px 0 24px;      margin: 0;      color: #1F69FF;          position: relative;      overflow: hidden;    }    .tg-df-container .tg-df-carousel-bg-circle-1 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-2 {      display: none;    }    .tg-df-container .tg-df-carousel-bg-circle-3 {      display: none;    }    .tg-df-container .tg-df-carousel-box-content {      position: relative;      z-index: 10;    }    .tg-df-container .tg-df-carousel-box-eyebrow {      background-color: transparent;      color: #1F69FF;      font-weight: 700;      font-size: 14px;      text-transform: uppercase;      letter-spacing: 1px;      display: inline-block;      padding: 0;      border-radius: 0;    }    .tg-df-container .tg-df-carousel-box-title {      font-size: 28px;      font-weight: 600;      line-height: 1.2;      margin-top: 8px;      color: #1e293b;    }    .tg-df-container .tg-df-countdown-wrapper {      position: absolute;      top: 0;      right: 0;      display: flex;      flex-direction: column;      align-items: flex-end;      gap: 12px;      transform: scale(0.67);      transform-origin: top right;    }    .tg-df-container .tg-df-countdown-title {      font-size: 16px;      text-align: center;      width: 100%;      font-weight: 600;      color: #011535;      margin: 0;    }    .tg-df-container .tg-df-countdown-blocks {      display: flex;      gap: 16px;    }    .tg-df-container .tg-df-countdown-item {      display: flex;      flex-direction: column;      align-items: center;      gap: 4px;    }    .tg-df-container .tg-df-countdown-box {      width: 59px;      height: 59px;      background: #03FE9E;      border-radius: 15px;      display: flex;      align-items: center;      justify-content: center;    }    .tg-df-container .tg-df-countdown-num {      font-family: 'Inter', sans-serif;      font-weight: 700;      font-size: 20px;      line-height: normal;      color: #011535;    }    .tg-df-container .tg-df-countdown-label {      font-family: 'Inter', sans-serif;      font-weight: 500;      font-size: 16px;      line-height: normal;      color: #1e293b;      text-transform: uppercase;    }    .tg-df-container .tg-df-carousel-box-subtitle {      font-size: 16px;      margin-top: 8px;      font-weight: 300;      color: #1e293b;      line-height: 24px;    }    .tg-df-container .tg-df-carousel-roundels-wrapper {      position: relative;      margin-top: 24px;      margin-left: -24px;      margin-right: -24px;    }    .tg-df-container .tg-df-carousel-roundels {      display: flex;      gap: 16px;      overflow-x: auto;            scrollbar-width: none;      padding-top: 12px;      padding-bottom: 24px;      padding-left: 24px;      padding-right: 24px;      margin-left: 0;      margin-right: 0;    }        .tg-df-container .tg-df-carousel-scroll-left,    .tg-df-container .tg-df-carousel-scroll-right {      position: absolute;      top: 50%;      transform: translateY(-50%);      height: 36px;      width: 36px;      display: flex;      align-items: center;      justify-content: center;      border-radius: 50%;      background-color: #ffffff;      border: 1px solid #e2e8f0;      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);      color: #1F69FF;      cursor: pointer;      transition: all 0.2s;      margin-top: -4px;      z-index: 20;    }    .tg-df-container .tg-df-carousel-scroll-left { left: 8px; }    .tg-df-container .tg-df-carousel-scroll-right { right: 8px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left { left: 0px; }    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right { right: 0px; }    .tg-df-carousel-filters-outer { margin-left: -24px; margin-right: -24px; padding-left: 24px; padding-right: 24px; }    @container tg-df (max-width: 599px) { .tg-df-carousel-filters-outer { margin-left: -16px; margin-right: -16px; padding-left: 16px; padding-right: 16px; } }        .tg-df-container .tg-df-carousel-scroll-left:hover,    .tg-df-container .tg-df-carousel-scroll-right:hover {      background-color: #f8fafc;      border-color: #cbd5e1;    }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-left,    .tg-df-carousel-filters-outer .tg-df-carousel-scroll-right {      background-color: rgba(255, 255, 255, 0.4);      border: none;      box-shadow: none;      backdrop-filter: blur(4px);      -webkit-backdrop-filter: blur(4px);    }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right { right: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-left { left: 0; }    .tg-df-grid-wrapper .tg-df-carousel-scroll-right { right: 0; }        .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-left:hover,    .tg-df-carousel-roundels-wrapper .tg-df-carousel-scroll-right:hover {      background-color: rgba(255, 255, 255, 0.6);      border: none;    }    .tg-df-container .tg-df-carousel-roundels::-webkit-scrollbar {      display: none;    }    .tg-df-container .tg-df-carousel-roundels::after {      content: "";      flex: 0 0 32px;    }    .tg-df-container .tg-df-roundel {      display: flex;      flex-direction: column;      align-items: center;      gap: 8px;      cursor: pointer;      min-width: 120px;      flex-shrink: 0;    }    .tg-df-container .tg-df-roundel-img-box {      width: 120px;      height: 120px;      border-radius: 50%;      background: white;      display: flex;      align-items: center;      justify-content: center;      overflow: hidden;      box-shadow: 0px 3px 14px 0px rgba(30, 41, 59, 0.08);      transition: box-shadow 0.2s;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-img-box {      box-shadow: 0 0 0 2px #E7F0FF, 0 0 0 4px #1F69FF;    }    .tg-df-container .tg-df-roundel:hover .tg-df-roundel-img-box img {      transform: scale(1.08);    }    .tg-df-container .tg-df-roundel-img-box img {      width: 100%;      height: 100%;      object-fit: contain;      padding: 10px;      box-sizing: border-box;      transition: transform 0.3s ease;    }    .tg-df-container .tg-df-roundel-label {      font-size: 13px;      font-weight: 400;      color: #1e293b;      text-align: center;      transition: font-weight 0.2s;    }    .tg-df-container .tg-df-roundel.active .tg-df-roundel-label {      font-weight: 700;    }    .tg-df-container .tg-df-carousel-filters-label {      font-size: 16px;      font-weight: 400;      color: #1e293b;      white-space: nowrap;      margin-right: 4px;    }    .tg-df-container .tg-df-carousel-filters-wrap {      display: flex;      align-items: center;      flex-wrap: nowrap;      gap: 8px;      margin-top: 8px;      overflow-x: auto;      scrollbar-width: none;      -webkit-overflow-scrolling: touch;      padding-bottom: 8px;      margin-left: -24px;      margin-right: -24px;      padding-left: 24px;      padding-right: 24px;    }    .tg-df-container .tg-df-carousel-filters-wrap::-webkit-scrollbar {      display: none;    }        .tg-df-container .tg-df-carousel-filter-btn img,    .tg-df-container .tg-df-carousel-filter-btn picture {      height: 20px;      width: 20px;      object-fit: contain;      object-position: center;      display: inline-flex;      align-items: center;      justify-content: center;      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn picture img {      margin-right: 0;      height: 100%;      width: 100%;    }    .tg-df-container .tg-df-carousel-filter-btn img.active-img,    .tg-df-container .tg-df-carousel-filter-btn picture:has(.active-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.inactive-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.inactive-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.inactive-img) {      display: none;    }    .tg-df-container .tg-df-carousel-filter-btn:hover img.active-img,    .tg-df-container .tg-df-carousel-filter-btn.active img.active-img,    .tg-df-container .tg-df-carousel-filter-btn:hover picture:has(.active-img),    .tg-df-container .tg-df-carousel-filter-btn.active picture:has(.active-img) {      display: inline-flex;    }    .tg-df-container .tg-df-carousel-filter-btn {      background: #ffffff;      border: 2px solid #1e293b;      color: #1e293b;      border-radius: 24px;      padding: 6px 16px;      font-size: 14px;      font-weight: 600;      cursor: pointer;      transition: all 0.2s;      flex-shrink: 0;      white-space: nowrap;      display: inline-flex;      align-items: center;      justify-content: center;      min-height: 36px;      box-sizing: border-box;    }    .tg-df-container .tg-df-carousel-filter-btn svg {      margin-right: 6px;    }    .tg-df-container .tg-df-carousel-filter-btn:hover {      background: #1e293b;      color: white;      border-color: #1e293b;    }    .tg-df-container .tg-df-carousel-filter-btn.active {      background: #1e293b;      color: white;      border-color: #1e293b;    }        .tg-df-grid.carousel-compact {      display: flex;      flex-wrap: nowrap;      overflow-x: auto;      gap: 16px;      padding: 16px 24px;      align-items: stretch;      scrollbar-width: none;    }    .tg-df-grid.carousel-compact::after {      content: "";      flex: 0 0 32px;    }    .tg-df-grid-wrapper {      position: relative;    }    .tg-df-grid.carousel-compact::-webkit-scrollbar {      display: none;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card {      flex: 0 0 auto;      width: 100px;      border-radius: 15px;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      border: 2px solid #1e293b;      background: white;      color: #1e293b;      display: flex;      flex-direction: column;      justify-content: center;      align-items: center;      font-weight: 600;      font-size: 14px;      cursor: pointer;      padding: 16px;      text-align: center;      transition: all 0.2s;    }    .tg-df-grid.carousel-compact .tg-df-load-more-card:hover {      background: #1e293b;      color: white;    }    .tg-df-grid.carousel-compact .tg-df-card {      flex: 0 0 auto;      width: 200px;      min-height: auto;      height: auto;      display: flex;      flex-direction: column;      border-radius: 15px;      border: none;      box-shadow: 0 0 16px rgba(0,0,0,0.08);      overflow: visible;    }    .tg-df-grid.carousel-compact .tg-df-card-image-box {      padding: 12px;      background-color: transparent;      border-radius: 15px 15px 0 0;      height: 130px;    }    .tg-df-grid.carousel-compact .tg-df-card-image {      mix-blend-mode: normal;    }    .tg-df-grid.carousel-compact .tg-df-card-discount-badge {      border-radius: 0;      top: 0px;      left: 0px;      padding: 4px 8px;      font-size: 11px;    }    .tg-df-grid.carousel-compact .tg-df-card-body {      padding: 8px 12px 12px 12px;    }    .tg-df-grid.carousel-compact .tg-df-card-title {      font-size: 14px;      font-weight: 400;      -webkit-line-clamp: 2;      margin-bottom: 8px;      color: #011535;    }    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):not(:has(.tg-df-tag-prime)):not(:has(.tg-df-coupon-wrapper:not([style*="none"]))) > .tg-df-card-title,    .tg-df-grid.carousel-compact .tg-df-card-body:not(:has(.tg-df-card-stars)):has(> .tg-df-card-title:first-child) > .tg-df-card-title {      -webkit-line-clamp: 3;    }    .tg-df-grid.carousel-compact .tg-df-card-cta {      border-radius: 5px;      padding: 8px 10px;      margin-top: 4px;      background-color: #1F69FF;    }    .tg-df-grid.carousel-compact .tg-df-card-price-group {      margin-bottom: 2px;    }    .tg-df-grid.carousel-compact .tg-df-card-merchant-pill {      margin-bottom: 2px;    }    @container tg-df (max-width: 599px) {      .tg-df-container .tg-df-carousel-blue-box-title {        font-size: 24px;      }      .tg-df-container .tg-df-countdown-title {        display: none;      }      .tg-df-container .tg-df-countdown-wrapper {        position: absolute;        top: 0;        right: 0;        align-items: flex-end;        transform: scale(0.45);        transform-origin: top right;      }      .tg-df-container .tg-df-roundel {        min-width: 88px;      }      .tg-df-container .tg-df-roundel-img-box {        width: 88px;        height: 88px;      }    }    /* REPLICA BLOCK STYLES */    .tg-df-grid.layout-replica-2 { grid-template-columns: repeat(2, 1fr) !important; gap: 20px; }    .tg-df-grid.layout-replica-1 { grid-template-columns: 1fr !important; gap: 20px; }        .tg-df-container .hawk-deal-widget-container { border-bottom: 1px solid #e5e7eb; display: flex; flex-direction: column; margin: 0; padding: 20px 0; box-sizing: border-box; font-family: inherit; }    .tg-df-container .hawk-deal-widget-wrap { display: flex; flex-direction: row; align-items: flex-start; width: 100%; gap: 24px; }    .tg-df-container .hawk-deal-widget-image-container { display: flex; flex-shrink: 0; justify-content: center; width: 160px; height: 160px; align-items: center; background: white; margin-bottom: 0px; }    .tg-df-container .hawk-deal-widget-title-product-title { color: #111827; font-size: 18px; font-weight: 700; line-height: 1.4; display: inline; }    .tg-df-container .hawk-deal-widget-title-price { font-size: 18px; font-weight: 700; line-height: 1.4; white-space: nowrap; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-price-now { font-weight: 700; }    .tg-df-container .hawk-deal-widget-title-retailer-price:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-title-retailer { font-size: 18px; font-weight: 700; line-height: 1.4; color: #2563eb; }    .tg-df-container .hawk-deal-widget-title-was-price { color: #dc2626; font-size: 16px; font-weight: 500; line-height: 1.4; text-decoration: line-through; white-space: nowrap; margin-left: 8px; margin-right: 8px; }    .tg-df-container .hawk-deal-widget-text-body-container { position: relative; width: 100%; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-text-body-main { font-size: 16px; width: 100%; margin-bottom: 12px; }    .tg-df-container .hawk-deal-widget-text-body-description { display: block; font-size: 15px; margin-top: 12px; color: #4b5563; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-body-description p { margin: 0; line-height: 1.6; }    .tg-df-container .hawk-deal-widget-text-cta-container { display: flex; flex-direction: column; gap: 12px; width: 100%; flex: 1; min-width: 0; box-sizing: border-box; }    .tg-df-container .hawk-deal-widget-footer { display: flex; justify-content: flex-end; width: 100%; margin-top: auto; }    .tg-df-container .hawk-deal-widget-button-wrapper { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; width: 100%; }    .tg-df-container .hawk-deal-widget-preferred-partner-wrapper { display: flex; flex-direction: row; }        @container tg-df (min-width: 600px) {      .tg-df-mobile-only { display: none !important; }    }    @container tg-df (max-width: 599px) {      .tg-df-desktop-only { display: none !important; }      .tg-df-grid.layout-replica-2 { grid-template-columns: 1fr !important; }      .tg-df-grid.savings-squad-cards { grid-template-columns: 1fr !important; display: flex; flex-direction: column; }    }    .tg-df-grid.savings-squad-cards .tg-df-card-title {      -webkit-line-clamp: unset !important;      display: block !important;      overflow: visible !important;    }    @container tg-df (max-width: 500px) {      .tg-df-container .hawk-deal-widget-wrap { display: block; }      .tg-df-container .hawk-deal-widget-image-container { display: block; float: left; margin: 0 16px 8px 0; width: 120px; max-width: 120px; height: auto; align-items: normal; justify-content: normal; }      .tg-df-container .hawk-deal-widget-text-cta-container { display: block; text-align: left; }      .tg-df-container .hawk-deal-widget-footer { display: block; margin-top: 16px; clear: both; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-deal-widget-button-wrapper .hawk-deal-widget-preferred-partner-wrapper { display: block; width: 100%; }      .tg-df-container .hawk-affiliate-link-deal-button { box-sizing: border-box !important; display: flex !important; max-width: none !important; width: 100% !important; margin: 0 !important; }    }        .tg-df-container .hawk-affiliate-link-deal-button {       align-items: center; background-color: #5aaf0b; box-sizing: border-box; color: #ffffff !important; display: flex; font-size: 14px; font-weight: 700; justify-content: center; letter-spacing: 0.5px; line-height: 1; min-width: 160px; padding: 14px 24px; text-align: center; text-decoration: none; text-transform: uppercase; width: 100%; word-break: normal; border-radius: 4px; border: 0; transition: background-color 0.2s;     }    .tg-df-container .hawk-affiliate-link-deal-button:hover { background-color: #4a9109; text-decoration: none; }    .tg-df-container .hawk-lazy-image-deal-widget { display: block; height: auto; margin: auto; max-height: 160px; max-width: 100%; mix-blend-mode: multiply; object-fit: contain; }    .tg-df-container .hawk-deal-widget-text-cta-container a { color: #2563eb; text-decoration: none; display: inline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover { text-decoration: underline; }    .tg-df-container .hawk-deal-widget-text-cta-container a:has(.hawk-deal-widget-title-product-title) { color: #111827; }    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-product-title,    .tg-df-container .hawk-deal-widget-text-cta-container a:hover .hawk-deal-widget-title-retailer-price { text-decoration: underline; }  \x3C/style>  \x3C!-- Widget Container --\x3E  \x3Cdiv class="tg-df-container" id="signal-deals-finder-root">    \x3C!-- Editor Floating Bar --\x3E    \x3Cdiv class="tg-df-editor-bar" id="tg-df-editor-bar" style="display:none;">      \x3Cdiv class="tg-df-editor-bar-text" style="display: flex; align-items: center;">        \x3Cspan id="tg-df-selected-count">0\x3C/span>\x26nbsp;Deals Selected        \x3Cbutton class="tg-df-editor-clear-btn" id="tg-df-editor-clear" type="button" style="margin-left: 12px; font-size: 13px; color: #9ca3af; background: none; border: none; cursor: pointer; text-decoration: underline;">Clear All\x3C/button>      \x3C/div>      \x3Cbutton class="tg-df-editor-copy-btn" id="tg-df-editor-copy" type="button">        \x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">\x3C/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">\x3C/path>\x3C/svg>        Copy to CMS      \x3C/button>    \x3C/div>    \x3Cdiv class="tg-df-carousel-host" id="tg-df-carousel-host" style="display: none;">      \x3Cdiv class="tg-df-carousel-eyebrow">DEAL FINDER\x3C/div>      \x3Cdiv class="tg-df-carousel-query-title" id="tg-df-carousel-title-label">Best Deals\x3C/div>            \x3Cdiv class="tg-df-carousel-blue-box">        \x3Cdiv class="tg-df-carousel-bg-circle-1" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-2" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-bg-circle-3" aria-hidden="true">\x26nbsp;\x3C/div>        \x3Cdiv class="tg-df-carousel-box-content">          \x3Cdiv class="tg-df-countdown-wrapper" id="tg-df-countdown-wrapper" style="display:none;">            \x3Cdiv class="tg-df-countdown-title" id="tg-df-countdown-title">Prime Day starts in\x3C/div>            \x3Cdiv class="tg-df-countdown-blocks">              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-days">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">DAYS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-hrs">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">HRS\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-min">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">MIN\x3C/div>\x3C/div>              \x3Cdiv class="tg-df-countdown-item">\x3Cdiv class="tg-df-countdown-box">\x3Cdiv class="tg-df-countdown-num" id="tg-df-cd-sec">0\x3C/div>\x3C/div>\x3Cdiv class="tg-df-countdown-label">SEC\x3C/div>\x3C/div>            \x3C/div>          \x3C/div>          \x3Cdiv class="tg-df-carousel-box-eyebrow">DEAL FINDER\x3C/div>          \x3Cdiv class="tg-df-carousel-box-title">Find Deals Fast\x3C/div>          \x3Cdiv class="tg-df-carousel-box-subtitle">The latest deals from the biggest retailers, all in one place\x3C/div>                    \x3Cdiv class="tg-df-carousel-roundels-wrapper">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-roundels">            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>            \x3Cdiv class="tg-df-roundel tg-df-roundel-skeleton">\x3Cdiv class="tg-df-roundel-img-box tg-df-skeleton">\x3C/div>\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="margin: 4px auto 0 auto; height: 13px; width: 48px;">\x3C/div>\x3C/div>          \x3C/div>          \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" onclick="this.parentElement.querySelector('.tg-df-carousel-roundels').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-carousel-filters-outer" style="position: relative;">          \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>          \x3Cdiv class="tg-df-carousel-filters-wrap">                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="0">All\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_lightning">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-ot="amazon_prime">              \x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>            \x3Cbutton class="tg-df-carousel-filter-btn" data-d="10">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 10% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="15">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 15% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-d="25">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>            Min 25% off\x3C/button>                      \x3Cbutton class="tg-df-carousel-filter-btn" data-pr="under50">              \x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>            Under $50\x3C/button>        \x3C/div>        \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('.tg-df-carousel-filters-wrap').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3C/div>    \x3C/div>    \x3C/div>      \x3C!-- Search & Filter Controls --\x3E    \x3Cdiv class="tg-df-controls" id="tg-df-controls" style="display:flex;">      \x3Cdiv class="tg-df-top-bar">        \x3Cdiv class="tg-df-search-wrapper">          \x3Cinput type="text" class="tg-df-search-input" placeholder="Search for deals, products, or brands...">          \x3Cbutton type="button" class="tg-df-search-btn" aria-label="Search">              \x3Csvg class="tg-df-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">                \x3Cpath d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>              \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-autocomplete-dropdown" id="tg-df-autocomplete">\x3C/div>        \x3C/div>                \x3Cdiv class="tg-df-settings-wrapper">          \x3Cbutton type="button" class="tg-df-settings-btn" aria-label="Settings" id="tg-df-settings-toggle">            \x3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20">                \x3Cpath d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.73 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .43-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.49-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/>            \x3C/svg>          \x3C/button>          \x3Cdiv class="tg-df-settings-dropdown-backdrop" id="tg-df-settings-backdrop">\x3C/div>          \x3Cdiv class="tg-df-settings-dropdown" id="tg-df-settings-panel">            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Search Region\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-region-select">                \x3Coption value="auto">🌍 Auto-detect\x3C/option>                \x3Coption value="US">🇺🇸 United States (US)\x3C/option>                \x3Coption value="GB">🇬🇧 United Kingdom (UK)\x3C/option>                \x3Coption value="CA">🇨🇦 Canada (CA)\x3C/option>                \x3Coption value="AU">🇦🇺 Australia (AU)\x3C/option>                \x3Coption value="DE">🇩🇪 Germany (DE)\x3C/option>                \x3Coption value="FR">🇫🇷 France (FR)\x3C/option>                \x3Coption value="IT">🇮🇹 Italy (IT)\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Retailer\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-retailer-select">                \x3Coption value="">All Retailers\x3C/option>                \x3Coption value="Amazon">Amazon\x3C/option>                \x3Coption value="Walmart">Walmart\x3C/option>                \x3Coption value="Best Buy">Best Buy\x3C/option>                \x3Coption value="Target">Target\x3C/option>                \x3Coption value="John Lewis">John Lewis\x3C/option>                \x3Coption value="Currys">Currys\x3C/option>                \x3Coption value="Argos">Argos\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Offer Type\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-offer-type-select">                \x3Coption value="">All Offers\x3C/option>                \x3Coption value="amazon_prime">Amazon Prime\x3C/option>                \x3Coption value="recommended_promo">Recommended Promo\x3C/option>                \x3Coption value="amazon_lightning">Amazon Lightning Deal\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">Result Count\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-rows-select">                \x3Coption value="3">3 Items\x3C/option>                \x3Coption value="4">4 Items\x3C/option>                \x3Coption value="6">6 Items\x3C/option>                \x3Coption value="12" selected>12 Items\x3C/option>                \x3Coption value="24">24 Items\x3C/option>                \x3Coption value="48">48 Items\x3C/option>              \x3C/select>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Deal Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Only show products with active offers or previous prices (was_price)\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-deal-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item tg-df-dl-row">              \x3Cdiv>                \x3Cspan class="tg-df-dl-row-text">Editor Mode\x3C/span>                \x3Cspan class="tg-df-dl-row-subtext">Enable multi-select to copy deals to CMS\x3C/span>              \x3C/div>              \x3Clabel class="tg-df-toggle">                \x3Cinput type="checkbox" id="tg-df-editor-mode">                \x3Cspan class="tg-df-slider">\x3C/span>              \x3C/label>            \x3C/div>            \x3Cdiv class="tg-df-setting-item">              \x3Clabel class="tg-df-setting-label">View Mode\x3C/label>              \x3Cselect class="tg-df-region-select" id="tg-df-view-mode-select">                \x3Coption value="auto">Auto Collection\x3C/option>                \x3Coption value="carousel">Carousel\x3C/option>                \x3Coption value="savings_squad">Savings Squad\x3C/option>                \x3Coption value="grid">Grid (Columns)\x3C/option>                \x3Coption value="row">Row (List)\x3C/option>              \x3C/select>            \x3C/div>          \x3C/div>        \x3C/div>      \x3C/div>      \x3Cdiv class="tg-df-filters">        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-category-filter-wrapper" style="display: none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-category-filter" aria-label="Category">            \x3Coption value="all">All Categories\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-multiselect-container" id="tg-df-brand-filter-wrapper" style="display:none;">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39A.998.998 0 0 0 18.95 4H5.04c-.83 0-1.3.95-.79 1.61z"/>          \x3C/svg>          \x3Cdiv class="tg-df-filter-select tg-df-multiselect-trigger" id="tg-df-brand-trigger" tabindex="0">            Any Brand          \x3C/div>          \x3Cdiv class="tg-df-multiselect-dropdown" id="tg-df-brand-dropdown">            \x3C!-- Populated via script --\x3E          \x3C/div>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M9 3L5 6.99h3V14h2V6.99h3L9 3zm7 14.01V10h-2v7.01h-3L15 21l4-3.99h-3z"/>          \x3C/svg>          \x3Cselect class="tg-df-sort-select" aria-label="Sort Deals">            \x3Coption value="date_desc">Newest First\x3C/option>            \x3Coption value="best_match">Sort by: Match\x3C/option>            \x3Coption value="price_asc">Price Low to High\x3C/option>            \x3Coption value="price_desc">Price High to Low\x3C/option>            \x3Coption value="discount_desc">Biggest Discount\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper tg-df-price-range-wrapper" id="tg-df-custom-price-wrapper" style="display: flex; align-items:center; justify-content:center; padding: 10px 20px; gap: 8px; border: 1px solid var(--tg-df-border); border-radius: 100px; background-color: var(--tg-df-bg);">          \x3Cspan style="font-size:14px; font-weight:500; color:var(--tg-df-text-primary);">Price\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-min" placeholder="Min" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">          \x3Cspan style="color:var(--tg-df-text-muted)">-\x3C/span>          \x3Cinput type="number" class="tg-df-price-input" id="tg-df-custom-price-max" placeholder="Max" style="width: 48px; background: transparent; border: none; color: var(--tg-df-text-primary); outline: none; font-size: 14px; text-align: center; padding: 0;">        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-legacy-price-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-price-filter" aria-label="Filter Prices">            \x3Coption value="all">All Prices\x3C/option>            \x3Coption value="under50">Under $50\x3C/option>            \x3Coption value="50_100">$50 - $100\x3C/option>            \x3Coption value="100_200">$100 - $200\x3C/option>            \x3Coption value="200_500">$200 - $500\x3C/option>            \x3Coption value="over500">Over $500\x3C/option>          \x3C/select>        \x3C/div>        \x3Cdiv class="tg-df-sort-wrapper" id="tg-df-discount-filter-wrapper">          \x3Csvg class="tg-df-sort-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">            \x3Cpath d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/>          \x3C/svg>          \x3Cselect class="tg-df-filter-select" id="tg-df-discount-filter" aria-label="Discount Amount">            \x3Coption value="all">Any discount\x3C/option>            \x3Coption value="5">Min 5%\x3C/option>            \x3Coption value="10">Min 10%\x3C/option>            \x3Coption value="15">Min 15%\x3C/option>            \x3Coption value="20">Min 20%\x3C/option>            \x3Coption value="25">Min 25%\x3C/option>            \x3Coption value="30">Min 30%\x3C/option>            \x3Coption value="40">Min 40%\x3C/option>            \x3Coption value="50">Min 50%\x3C/option>            \x3Coption value="60">Min 60%\x3C/option>            \x3Coption value="70">Min 70%\x3C/option>          \x3C/select>        \x3C/div>      \x3C/div>    \x3C/div>    \x3C!-- Deals Grid Wrapper --\x3E    \x3Cdiv class="tg-df-grid-wrapper tg-df-carousel-cards-wrapper" id="tg-df-grid-wrapper">      \x3Cbutton class="tg-df-carousel-scroll-left" type="button" aria-label="Scroll left" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: -200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m15 18-6-6 6-6">\x3C/path>\x3C/svg>\x3C/button>      \x3Cdiv class="tg-df-grid" id="tg-df-grid">        \x3C!-- Content populated by JavaScript --\x3E      \x3C/div>      \x3Cbutton class="tg-df-carousel-scroll-right" type="button" aria-label="Scroll right" style="display:none;" onclick="this.parentElement.querySelector('#tg-df-grid').scrollBy({left: 200, behavior: 'smooth'})">\x3Csvg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpath d="m9 18 6-6-6-6">\x3C/path>\x3C/svg>\x3C/button>    \x3C/div>        \x3C!-- Vouchers Modal --\x3E    \x3Cdiv class="tg-df-modal-backdrop" id="tg-df-vouchers-modal">      \x3Cdiv class="tg-df-modal">        \x3Cdiv class="tg-df-modal-header">          \x3Ch3 class="tg-df-modal-title" id="tg-df-vouchers-title">Available Coupons & Deals\x3C/h3>          \x3Cbutton class="tg-df-modal-close" id="tg-df-vouchers-close">            \x3Csvg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">              \x3Cline x1="18" y1="6" x2="6" y2="18">\x3C/line>              \x3Cline x1="6" y1="6" x2="18" y2="18">\x3C/line>            \x3C/svg>          \x3C/button>        \x3C/div>        \x3Cdiv class="tg-df-modal-body" id="tg-df-vouchers-content">          \x3C!-- Vouchers injected here --\x3E        \x3C/div>      \x3C/div>    \x3C/div>  \x3C/div>`;      if (!template) {        template = document.createElement('template');        template.innerHTML = rawTemplate;      }      let shadowRoot = null;      if (hostContainer && template) {        hostContainer.setAttribute('data-initialized', 'true');        shadowRoot = hostContainer.attachShadow({ mode: 'open' });        shadowRoot.appendChild(template.content.cloneNode(true));      }      class DealsFinderWidget {        constructor(config) {          this.rootNode = config.rootNode || document;          this.hostContainer = config.hostContainer || null;          this.rootId = config.rootId || 'signal-deals-finder-root';          this.root = this.rootNode.querySelector('#' + this.rootId);          if (!this.root) return;          this.widgetId = (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'widget-' + Date.now() + '-' + Math.random().toString(36).slice(2);          this.grid = this.root.querySelector('#tg-df-grid');          this.tagsContainer = this.root.querySelector('#tg-df-tags-container');          this.categoryFilter = this.root.querySelector('#tg-df-category-filter');          this.categoryFilterWrapper = this.root.querySelector('#tg-df-category-filter-wrapper');          this.searchInput = this.root.querySelector('.tg-df-search-input');          this.autocompleteDropdown = this.root.querySelector('#tg-df-autocomplete');          this.sortSelect = this.root.querySelector('.tg-df-sort-select');          this.searchBtn = this.root.querySelector('.tg-df-search-btn');                    this.settingsToggle = this.root.querySelector('#tg-df-settings-toggle');          this.settingsPanel = this.root.querySelector('#tg-df-settings-panel');          this.settingsBackdrop = this.root.querySelector('#tg-df-settings-backdrop');          this.regionSelect = this.root.querySelector('#tg-df-region-select');          this.retailerSelect = this.root.querySelector('#tg-df-retailer-select');          this.offerTypeSelect = this.root.querySelector('#tg-df-offer-type-select');          this.viewModeSelect = this.root.querySelector('#tg-df-view-mode-select');          this.rowsSelect = this.root.querySelector('#tg-df-rows-select');          this.dealModeToggle = this.root.querySelector('#tg-df-deal-mode');          this.editorModeToggle = this.root.querySelector('#tg-df-editor-mode');          this.priceFilter = this.root.querySelector('#tg-df-price-filter');          this.discountFilter = this.root.querySelector('#tg-df-discount-filter');                    this.editorBar = this.root.querySelector('#tg-df-editor-bar');          this.editorSelectedCount = this.root.querySelector('#tg-df-selected-count');          this.editorCopyBtn = this.root.querySelector('#tg-df-editor-copy');          this.editorClearBtn = this.root.querySelector('#tg-df-editor-clear');                    this.apiUrl = 'https://search-api.fie.future.net.uk/widget.php';          this.deals = [];          this.displayLimit = 12;          this.airedaleArticles = null;          this.airedaleTags = [];          this.airedaleTagCounts = {};          this.activeDealTag = null;          this.selectedBrands = [];          this.currentQuery = '';          this.editorMode = this.hostContainer ? this.hostContainer.hasAttribute('data-editor-mode') : false;          this.viewModeOverride = this.hostContainer ? this.hostContainer.getAttribute('data-view-mode') : null;          this.selectedDeals = new Map();                    this.brandFilterWrapper = this.root.querySelector('#tg-df-brand-filter-wrapper');          this.brandTrigger = this.root.querySelector('#tg-df-brand-trigger');          this.brandDropdown = this.root.querySelector('#tg-df-brand-dropdown');                    this.customPriceWrapper = this.root.querySelector('#tg-df-custom-price-wrapper');          this.customPriceMin = this.root.querySelector('#tg-df-custom-price-min');          this.customPriceMax = this.root.querySelector('#tg-df-custom-price-max');          this.legacyPriceWrapper = this.root.querySelector('#tg-df-legacy-price-wrapper');          this.discountFilterWrapper = this.root.querySelector('#tg-df-discount-filter-wrapper');          this.initResizeObserver();          this.init();            if (['carousel', 'carousel-compact', 'auto', 'grid', 'row'].includes(this.getViewMode())) { this.loadCarouselSpreadsheet(); }        }        getViewMode() {          if (this.viewModeOverride && (!this.editorMode || !this.viewModeSelect)) {            return this.viewModeOverride;          }          return (this.viewModeSelect && this.viewModeSelect.value) ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');        }        applyLayoutMode() {          if (!this.grid) return;          const mode = this.getViewMode();          this.grid.classList.remove('layout-row', 'layout-grid', 'tg-df-grid-auto', 'carousel-compact', 'layout-replica-1', 'layout-replica-2');                    const carouselHost = this.root.querySelector('#tg-df-carousel-host');          const controlsDiv = this.root.querySelector('#tg-df-controls');          if (mode === 'carousel' || mode === 'auto' || mode === 'grid' || mode === 'row') {             if (mode === 'carousel') this.grid.classList.add('carousel-compact');             if (carouselHost) carouselHost.style.display = 'block';             if (controlsDiv) controlsDiv.style.display = 'none';             if (this.root.classList.contains('tg-df-container') && mode === 'carousel') {               this.root.classList.add('is-carousel');             } else if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          } else {             if (carouselHost) carouselHost.style.display = 'none';             if (controlsDiv) controlsDiv.style.display = 'flex';             if (this.root.classList.contains('tg-df-container')) {               this.root.classList.remove('is-carousel');             }          }          if (mode === 'grid') {            this.grid.classList.add('layout-grid');          } else if (mode === 'row') {            this.grid.classList.add('layout-row');          } else if (mode === 'savings_squad') {            this.grid.classList.add('tg-df-grid-auto', 'savings-squad-cards');          } else if (mode !== 'carousel') {            this.grid.classList.add('tg-df-grid-auto');          }                    const settingsWrapper = this.root.querySelector('.tg-df-settings-wrapper');          if (settingsWrapper) {            settingsWrapper.style.display = mode === 'auto' ? 'none' : 'block';          }          if (this.customPriceWrapper) {             this.customPriceWrapper.style.display = mode === 'auto' ? 'flex' : 'none';          }          if (this.legacyPriceWrapper) {             this.legacyPriceWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }          if (this.discountFilterWrapper) {             this.discountFilterWrapper.style.display = mode === 'auto' ? 'none' : 'flex';          }        }        initResizeObserver() {          try {            if (window.parent === window) return;          } catch (e) {            // cross origin frame check threw          }          const emitHeight = () => {            try {              const height = document.documentElement.scrollHeight || document.body.scrollHeight;              const msg = { type: 'embed-size', height: height };              if (window.parent && window.parent !== window) {                window.parent.postMessage(msg, '*');                window.parent.postMessage(JSON.stringify({ ...msg, sentinel: 'amp' }), '*');              }            } catch (e) {}          };                    if (window.ResizeObserver) {            try {              const ro = new ResizeObserver(() => emitHeight());              ro.observe(document.body);              if (this.root) ro.observe(this.root);            } catch(e){ console.warn(e); }          }          window.addEventListener('resize', emitHeight);          setTimeout(emitHeight, 300);        }        initCountdown() {          this.cdWrapper = this.root.querySelector('#tg-df-countdown-wrapper');                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          this.showCountdown = params.get('show_countdown') === 'true';          const showHeaderDetails = params.get('show_header_details') !== 'false';          const eyebrow = this.root.querySelector('.tg-df-carousel-box-eyebrow');          const title = this.root.querySelector('.tg-df-carousel-box-title');          const subtitle = this.root.querySelector('.tg-df-carousel-box-subtitle');          if (!showHeaderDetails) {            let containerElement = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (containerElement) containerElement.classList.add('hide-header-details');            if (eyebrow) eyebrow.style.display = 'none';            if (title) title.style.display = 'none';            if (subtitle) subtitle.style.display = 'none';          }          if (!this.cdWrapper) return;          this.cdTitle = this.root.querySelector('#tg-df-countdown-title');          this.cdDays = this.root.querySelector('#tg-df-cd-days');          this.cdHrs = this.root.querySelector('#tg-df-cd-hrs');          this.cdMin = this.root.querySelector('#tg-df-cd-min');          this.cdSec = this.root.querySelector('#tg-df-cd-sec');          this.updateCountdown();          this.cdInterval = setInterval(() => this.updateCountdown(), 1000);        }        updateCountdown() {          if (!this.cdWrapper) return;          if (!this.showCountdown) {            this.cdWrapper.style.display = 'none';            return;          }          const area = this.getAreaCode();          let offset = '-04:00';          if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(area)) {             offset = '+02:00';          } else if (['GB', 'IE', 'UK'].includes(area)) {             offset = '+01:00';          }          const startTime = new Date('2026-06-23T00:00:00' + offset).getTime();          const endTime = new Date('2026-06-26T00:00:00' + offset).getTime();          const now = Date.now();          let targetTime = 0;          if (now < startTime) {             targetTime = startTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day starts in';             this.cdWrapper.style.display = 'flex';          } else if (now < endTime) {             targetTime = endTime;             if (this.cdTitle) this.cdTitle.textContent = 'Prime Day ends in';             this.cdWrapper.style.display = 'flex';          } else {             this.cdWrapper.style.display = 'none';             if (this.cdInterval) clearInterval(this.cdInterval);             return;          }          const diff = Math.max(0, targetTime - now);          const d = Math.floor(diff / (1000 * 60 * 60 * 24));          const h = Math.floor((diff / (1000 * 60 * 60)) % 24);          const m = Math.floor((diff / 1000 / 60) % 60);          const s = Math.floor((diff / 1000) % 60);          if (this.cdDays) this.cdDays.textContent = d;          if (this.cdHrs) this.cdHrs.textContent = h;          if (this.cdMin) this.cdMin.textContent = m;          if (this.cdSec) this.cdSec.textContent = s;        }        init() {          this.initCountdown();          try {            initAnalytics();          } catch (e) {            console.warn('Deals Widget Analytics Error:', e);          }                    this.bindEvents();                    let initialQuery = '';                    let searchSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {            searchSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {            searchSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(searchSource);          let initialViewMode = params.get('view_mode');          if (!params.has('search') && !params.has('q') && !params.has('query') && initialViewMode !== 'savings_squad') {             initialQuery = 'Everything';             if (this.discountFilter && !params.has('min_discount_ratio')) {               this.discountFilter.value = '5';             }          }          const website = params.get('website') || 'tomsguide';          this.website = website;          if (website === 'techradar') {            const squadHeader = this.root.querySelector('.tg-df-savings-squad-header');            if (squadHeader) {               const pic = squadHeader.querySelector('picture');               if (pic) pic.style.display = 'none';            }            const style = document.createElement('style');            style.innerHTML = `              .tg-df-container .hawk-affiliate-link-deal-button, .tg-df-container .tg-df-card-cta { background-color: #5DAF08 !important; }              .tg-df-container .hawk-affiliate-link-deal-button:hover, .tg-df-container .tg-df-card-cta:hover { background-color: #4a8c06 !important; }            `;            this.root.appendChild(style);          }                    if (this.regionSelect) {            this.regionSelect.value = params.get('region') || 'auto';            this.updatePriceDropdownCurrency();          }                    if (this.retailerSelect && params.has('retailer')) {            this.retailerSelect.value = params.get('retailer');          }                    if (params.has('brands')) {            const b = params.get('brands');            if (b) {              this.selectedBrands = b.split(',');            }          }                    if (this.offerTypeSelect && params.has('offer_type')) {            this.offerTypeSelect.value = params.get('offer_type');          }          if (params.has('bg_color')) {            const bg = params.get('bg_color');            if (bg === 'white') {              this.root.style.setProperty('background-color', '#ffffff', 'important');            } else if (bg === 'transparent') {              this.root.style.setProperty('background-color', 'transparent', 'important');            } else if (bg === 'light_blue') {              this.root.style.setProperty('background-color', '#E7F0FF', 'important');            }          } else {             this.root.style.removeProperty('background-color');          }                    if (params.has('view_mode')) {            if (this.viewModeSelect) {              this.viewModeSelect.value = params.get('view_mode');            } else {              this.viewModeOverride = params.get('view_mode');            }          }          if (this.rowsSelect && params.has('rows')) {            this.rowsSelect.value = params.get('rows');          }          if (params.has('price')) {            const priceVal = params.get('price');            if (this.priceFilter) {               // Try assigning it directly to select. If it's not present implicitly ignores               this.priceFilter.value = priceVal;            }            if (priceVal.includes('_')) {               const parts = priceVal.split('_');               if (this.customPriceMin && parts[0]) this.customPriceMin.value = parts[0];               if (this.customPriceMax && parts[1]) this.customPriceMax.value = parts[1];            }          }          if (this.discountFilter && params.has('min_discount_ratio')) {            // Need to convert back from ratio (e.g. 0.8) to select value (e.g. "20")            const ratioStr = params.get('min_discount_ratio');            const ratioFloat = parseFloat(ratioStr);            if (!isNaN(ratioFloat)) {               const percentage = Math.round((1 - ratioFloat) * 100);               this.discountFilter.value = percentage.toString();            }          }          if (this.sortSelect) {            this.sortSelect.value = params.get('sort') || 'discount_desc';          }          if (this.dealModeToggle && params.has('deal_mode')) {            this.dealModeToggle.checked = params.get('deal_mode') === 'true' || params.get('deal_mode') === '1';          }                    // Re-apply layout after params have updated control values          this.applyLayoutMode();                    if (params.get('search')) {            initialQuery = params.get('search');          } else if (params.get('q')) {            initialQuery = params.get('q');          } else if (params.get('query')) {            initialQuery = params.get('query');          }                    this.currentQuery = initialQuery;          if (this.searchInput) {            this.searchInput.value = this.currentQuery;          }                    if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {            this.fetchDeals(this.currentQuery);          } else {            this.render();          }        }        updatePriceDropdownCurrency() {          if (!this.priceFilter || !this.regionSelect) return;          const currencySymbols = {            'US': '$',            'GB': '£',            'CA': '$CA',            'AU': '$AU',            'DE': '€',            'FR': '€',            'IT': '€',          };          const area = this.getAreaCode();          const cur = currencySymbols[area || 'US'] || '$';                    const options = this.priceFilter.options;          for (let i = 0; i < options.length; i++) {            const opt = options[i];            if (opt.value === 'all') {              opt.innerText = 'All Prices';            } else if (opt.value === 'under50') {              opt.innerText = `Under ${cur}50`;            } else if (opt.value === '50_100') {              opt.innerText = `${cur}50 - ${cur}100`;            } else if (opt.value === '100_200') {              opt.innerText = `${cur}100 - ${cur}200`;            } else if (opt.value === '200_500') {              opt.innerText = `${cur}200 - ${cur}500`;            } else if (opt.value === 'over500') {              opt.innerText = `Over ${cur}500`;            }          }        }        populateBrandDropdown(values) {          if (!this.brandDropdown || !this.brandFilterWrapper) return;          this.brandFilterWrapper.style.display = 'flex'; // show the wrapper                    let html = '';          const allChecked = this.selectedBrands.length === 0 ? 'checked' : '';          const _div = '<' + '/div>';          const _span = '<' + '/span>';          html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="" ${allChecked} class="tg-df-brand-chk"> Any Brand${_div}`;                    values.forEach(v => {             if (!v.formatted_value || v.formatted_value === 'Any Brand') return;             const isChecked = this.selectedBrands.includes(v.formatted_value) ? 'checked' : '';             html += `\x3Cdiv class="tg-df-ms-option">\x3Cinput type="checkbox" value="${this.escapeHTML(v.formatted_value)}" ${isChecked} class="tg-df-brand-chk"> ${this.escapeHTML(v.formatted_value)} \x3Cspan style="color:var(--tg-df-text-muted);font-size:12px">(${v.count || 0})${_span}${_div}`;          });                    this.brandDropdown.innerHTML = html;                    // Re-bind listeners          const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');          chks.forEach(chk => {            chk.addEventListener('change', (e) => {              const val = e.target.value;              if (val === '') {                this.selectedBrands = [];              } else {                if (e.target.checked) {                   if (!this.selectedBrands.includes(val)) this.selectedBrands.push(val);                } else {                   this.selectedBrands = this.selectedBrands.filter(b => b !== val);                }              }                            if (this.selectedBrands.length === 0) {                 this.brandTrigger.innerText = 'Any Brand';              } else if (this.selectedBrands.length === 1) {                 this.brandTrigger.innerText = this.selectedBrands[0];              } else {                 this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;              }                            // Only call API if changed from UI interactions              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.updateURLParams();                 this.fetchDeals(this.currentQuery);              }            });          });                    // Update button text on load          if (this.selectedBrands.length === 0) {             this.brandTrigger.innerText = 'Any Brand';          } else if (this.selectedBrands.length === 1) {             this.brandTrigger.innerText = this.selectedBrands[0];          } else {             this.brandTrigger.innerText = `${this.selectedBrands.length} Brands selected`;          }        }        updateURLParams() {          const url = new URL(window.location);          if (this.currentQuery && this.currentQuery !== 'Gaming laptops') {            url.searchParams.set('q', this.currentQuery);          } else {            url.searchParams.delete('q');            url.searchParams.delete('search');            url.searchParams.delete('query');          }                    if (this.regionSelect && this.regionSelect.value !== 'auto') {            url.searchParams.set('region', this.regionSelect.value);          } else {            url.searchParams.delete('region');          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.set('retailer', this.retailerSelect.value);          } else {            url.searchParams.delete('retailer');          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.set('brands', this.selectedBrands.join(','));          } else {            url.searchParams.delete('brands');          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.set('offer_type', this.offerTypeSelect.value);          } else {            url.searchParams.delete('offer_type');          }                    if (this.viewModeSelect && this.viewModeSelect.value !== 'auto') {            url.searchParams.set('view_mode', this.viewModeSelect.value);          } else {            url.searchParams.delete('view_mode');          }                    if (this.rowsSelect && this.rowsSelect.value !== '12') {            url.searchParams.set('rows', this.rowsSelect.value);          } else {            url.searchParams.delete('rows');          }                    const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             url.searchParams.set('price', `${min}_${max}`);          } else if (this.priceFilter && this.priceFilter.value !== 'all') {            url.searchParams.set('price', this.priceFilter.value);          } else {            url.searchParams.delete('price');          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {               const ratio = (100 - v) / 100;               url.searchParams.set('min_discount_ratio', ratio.toString());            }          } else {            url.searchParams.delete('min_discount_ratio');          }                    if (this.sortSelect && this.sortSelect.value !== 'discount_desc') {            url.searchParams.set('sort', this.sortSelect.value);          } else {            url.searchParams.delete('sort');          }                    if (this.dealModeToggle && this.dealModeToggle.checked) {            url.searchParams.set('deal_mode', 'true');          } else {            url.searchParams.delete('deal_mode');          }                    window.history.replaceState({}, '', url);        }        bindEvents() {          const roundels = this.root.querySelectorAll('.tg-df-carousel-cat.original-hardcoded');          roundels.forEach(r => {             r.addEventListener('click', () => {                const q = r.getAttribute('data-query');                const pr = r.getAttribute('data-pr');                if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: q,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = q;                const label = this.root.querySelector('#tg-df-carousel-title-label');                if (label) label.textContent = 'Best ' + q;                if (this.priceFilter) this.priceFilter.value = pr || 'all';                if (this.discountFilter) this.discountFilter.value = '5';                if (this.searchInput) this.searchInput.value = q;                                roundels.forEach(ro => ro.classList.remove('active'));                r.classList.add('active');                this.fetchDeals(this.currentQuery);             });          });          const discBtns = this.root.querySelectorAll('.tg-df-carousel-filter-btn');          discBtns.forEach(b => {             b.addEventListener('click', () => {                const d = b.getAttribute('data-d');                const pr = b.getAttribute('data-pr');                const ot = b.getAttribute('data-ot');                let label = b.innerText ? b.innerText.trim() : '';                let filterType = 'unknown';                let filterVal = 'unknown';                if (d !== null) { filterType = 'discount'; filterVal = d; }                else if (pr !== null) { filterType = 'price'; filterVal = pr; }                else if (ot !== null) { filterType = 'offertype'; filterVal = ot; }                if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-${filterType}-${filterVal}`, name: 'Filter Button', label: label });                                if (d !== null) {                   if (this.discountFilter) this.discountFilter.value = this.discountFilter.value === d ? '0' : d;                } else if (pr !== null) {                   if (this.priceFilter) this.priceFilter.value = this.priceFilter.value === pr ? 'all' : pr;                } else if (ot !== null) {                   if (this.offerTypeSelect) this.offerTypeSelect.value = this.offerTypeSelect.value === ot ? 'all' : ot;                } else {                   if (this.discountFilter) this.discountFilter.value = '0';                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.offerTypeSelect) this.offerTypeSelect.value = 'all';                }                if (d === null && pr === null && ot === null && b.getAttribute("data-type") !== "custom") {                   discBtns.forEach(ro => ro.classList.remove('active'));                   b.classList.add('active');                } else if (b.getAttribute("data-type") !== "custom") {                   // Only operate on hardcoded buttons (those without data-type)                   discBtns.forEach(ro => {                      if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active');                   });                                      let makeActive = true;                   if (d !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-d') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (pr !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-pr') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   } else if (ot !== null) {                       if (b.classList.contains('active')) makeActive = false;                       discBtns.forEach(ro => { if (ro.getAttribute('data-ot') !== null && ro.getAttribute('data-type') !== 'custom') ro.classList.remove('active') });                   }                                      if (makeActive) b.classList.add('active');                                      // Check if anything is active, if not activate "All"                   let anyActive = false;                   discBtns.forEach(ro => { if (ro.classList.contains('active') && ro.getAttribute('data-type') !== 'custom') anyActive = true; });                   if (!anyActive) {                       discBtns.forEach(ro => { if (!ro.getAttribute('data-d') && !ro.getAttribute('data-pr') && !ro.getAttribute('data-ot') && ro.getAttribute('data-type') !== 'custom') ro.classList.add('active'); });                   }                }                                this.fetchDeals(this.currentQuery);             });          });          if (this.brandTrigger && this.brandDropdown) {            this.brandTrigger.addEventListener('click', () => {              this.brandDropdown.classList.toggle('active');            });            document.addEventListener('click', (e) => {              if (this.brandFilterWrapper && !e.composedPath().includes(this.brandFilterWrapper)) {                this.brandDropdown.classList.remove('active');              }            });          }          let debounceTimer;          if(this.searchInput) {            this.searchInput.addEventListener('input', (e) => {              clearTimeout(debounceTimer);              const query = e.target.value.trim();              this.currentQuery = query;              if (this.getViewMode() === 'savings_squad' && this.autocompleteDropdown && this.airedaleTags && query.length > 0) {                 const matches = this.airedaleTags.filter(t => t.toLowerCase().includes(query.toLowerCase()) && t.toLowerCase() !== query.toLowerCase()).slice(0, 5);                 if (matches.length > 0) {                    this.autocompleteDropdown.innerHTML = matches.map(m => `\x3Cdiv class="tg-df-autocomplete-item" data-tag="${this.escapeHTML(m)}">${this.escapeHTML(m)}<` + `/div>`).join('');                    this.autocompleteDropdown.classList.add('active');                 } else {                    this.autocompleteDropdown.classList.remove('active');                 }              } else if (this.autocompleteDropdown) {                 this.autocompleteDropdown.classList.remove('active');              }              debounceTimer = setTimeout(() => {                this.updateURLParams();                if (query.length > 2) {                  this.fetchDeals(query);                } else if (query.length === 0) {                  this.deals = [];                  this.render();                }              }, 400);            });            this.searchInput.addEventListener('keypress', (e) => {              if (e.key === 'Enter') {                if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');                clearTimeout(debounceTimer);                const query = e.target.value.trim();                this.currentQuery = query;                this.activeDealTag = null;                trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });                this.updateURLParams();                if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                   this.fetchDeals(query);                }              }            });          }          if (this.autocompleteDropdown) {             this.autocompleteDropdown.addEventListener('click', (e) => {                const item = e.target.closest('.tg-df-autocomplete-item');                if (item) {                   const tag = item.getAttribute('data-tag');                   this.currentQuery = tag;                   if (this.searchInput) this.searchInput.value = tag;                   this.activeDealTag = tag;                   this.autocompleteDropdown.classList.remove('active');                   this.updateURLParams();                   this.fetchDeals(tag);                }             });             document.addEventListener('click', (e) => {               if (this.autocompleteDropdown && this.searchInput && !e.composedPath().includes(this.searchInput) && !e.composedPath().includes(this.autocompleteDropdown)) {                 this.autocompleteDropdown.classList.remove('active');               }             });          }          if (this.searchBtn) {            this.searchBtn.addEventListener('click', () => {              if (this.autocompleteDropdown) this.autocompleteDropdown.classList.remove('active');              clearTimeout(debounceTimer);              const query = this.searchInput.value.trim();              trackElementInteraction({ id: 'search-submit', name: 'Ask', label: 'Ask (main search)', text: query });              this.activeDealTag = null;              this.currentQuery = query;              this.updateURLParams();              if (query.length > 2 || (this.getViewMode() === 'savings_squad')) {                 this.fetchDeals(query);              }            });          }          if(this.sortSelect) this.sortSelect.addEventListener('change', () => {            trackElementInteraction({ id: `sort-option-${this.sortSelect.value}`, name: 'Sort', label: `Sort: ${this.sortSelect.options[this.sortSelect.selectedIndex].text}` });            this.updateURLParams();            if (this.deals.length > 0) {              this.sortData();              this.render();            }          });                    const priceFilter = this.root.querySelector('#tg-df-price-filter');          if (priceFilter) {            this.priceFilter = priceFilter;            this.priceFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-price-${this.priceFilter.value}`, name: 'Price', label: this.priceFilter.options[this.priceFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          const updateCustomPrice = () => {             this.updateURLParams();             if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);             } else {                this.render();             }          };          if (this.customPriceMin) {             this.customPriceMin.addEventListener('change', updateCustomPrice);             this.customPriceMin.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          if (this.customPriceMax) {             this.customPriceMax.addEventListener('change', updateCustomPrice);             this.customPriceMax.addEventListener('keypress', (e) => {                if (e.key === 'Enter') updateCustomPrice();             });          }          const discountFilter = this.root.querySelector('#tg-df-discount-filter');          if (discountFilter) {            this.discountFilter = discountFilter;            this.discountFilter.addEventListener('change', () => {              trackElementInteraction({ id: `filter-discount-${this.discountFilter.value}`, name: 'Discount', label: this.discountFilter.options[this.discountFilter.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }            });          }          if (this.categoryFilter) {            this.categoryFilter.addEventListener('change', (e) => {               const val = e.target.value === 'all' ? null : e.target.value;               this.activeDealTag = val;               this.fetchSavingsSquad();            });          }                    if (this.settingsToggle) {            this.settingsToggle.addEventListener('click', () => {              const o = this.settingsPanel.classList.toggle('active');              this.settingsBackdrop.classList.toggle('active');              if (o) trackElementInteraction({ id: 'filter-open', name: 'Filters', label: 'Open filters' });            });          }                    if (this.settingsBackdrop) {            this.settingsBackdrop.addEventListener('click', () => {              this.settingsPanel.classList.remove('active');              this.settingsBackdrop.classList.remove('active');            });          }                    if (this.regionSelect) {            this.regionSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-region-${this.regionSelect.value}`, name: 'Region', label: this.regionSelect.options[this.regionSelect.selectedIndex].text });              this.updateURLParams();              this.updatePriceDropdownCurrency();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.retailerSelect) {            this.retailerSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-merchant-${this.retailerSelect.value}`, name: 'Retailer', label: this.retailerSelect.options[this.retailerSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.offerTypeSelect) {            this.offerTypeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-offertype-${this.offerTypeSelect.value}`, name: 'Offer Type', label: this.offerTypeSelect.options[this.offerTypeSelect.selectedIndex].text });              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.viewModeSelect) {            this._prevViewMode = this.viewModeSelect.value;            this.viewModeSelect.addEventListener('change', () => {              trackElementInteraction({ id: `filter-viewmode-${this.viewModeSelect.value}`, name: 'View Mode', label: this.viewModeSelect.options[this.viewModeSelect.selectedIndex].text });                            // Reset all active toggles and filters to prevent config carry-over              this.selectedBrands = [];              if (this.brandTrigger) this.brandTrigger.innerText = 'Select Brands';              if (this.brandDropdown) {                const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                chks.forEach(chk => { chk.checked = false; });              }              if (this.priceFilter) this.priceFilter.value = 'all';              if (this.customPriceMin) this.customPriceMin.value = '';              if (this.customPriceMax) this.customPriceMax.value = '';              if (this.sortSelect) this.sortSelect.value = this.viewModeSelect.value === 'savings_squad' ? 'date_desc' : 'discount_desc';              if (this.discountFilter) this.discountFilter.value = '0';              if (this.retailerSelect) this.retailerSelect.value = '';              if (this.offerTypeSelect) this.offerTypeSelect.value = '';              if (this.rowsSelect) this.rowsSelect.value = '12';              if (this.categoryFilter) this.categoryFilter.value = 'all';              this.activeDealTag = null;              this.updateURLParams();              this.applyLayoutMode();                            if (this.getViewMode() === 'savings_squad' || this._prevViewMode === 'savings_squad') {                this.fetchDeals(this.currentQuery);              } else {                this.render();              }              this._prevViewMode = this.viewModeSelect.value;            });          }                    if (this.rowsSelect) {            this.rowsSelect.addEventListener('change', () => {              this.updateURLParams();              if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {                this.fetchDeals(this.currentQuery);              }            });          }                    if (this.dealModeToggle) {            this.dealModeToggle.addEventListener('change', () => {              this.updateURLParams();              this.render();            });          }          if (this.editorModeToggle) {             this.editorModeToggle.addEventListener('change', (e) => {                this.editorMode = e.target.checked;                this.render();                this.updateFloatingCopyBar();             });          }          if (this.editorCopyBtn) {             this.editorCopyBtn.addEventListener('click', () => {                this.copySelectedDealsToCMS();             });          }          if (this.editorClearBtn) {             this.editorClearBtn.addEventListener('click', () => {                this.selectedDeals.clear();                this.render();                this.updateFloatingCopyBar();             });          }          if (this.grid) {            this.grid.addEventListener('change', (e) => {               if (e.target.classList.contains('tg-df-deal-checkbox')) {                  const dealId = e.target.getAttribute('data-id');                  if (e.target.checked) {                     const dealObj = this.deals.find(d => d.id === dealId);                     if (dealObj) this.selectedDeals.set(dealId, dealObj);                  } else {                     this.selectedDeals.delete(dealId);                  }                  this.updateFloatingCopyBar();               }            });            this.grid.addEventListener('click', (e) => {              const dealCard = e.target.closest('[data-action="deal-click"]');              const similarCard = e.target.closest('[data-action="view-similar-click"]');              const cardLink = dealCard || similarCard;              if (cardLink) {                const productName = cardLink.getAttribute('data-product-name');                const merchantName = cardLink.getAttribute('data-merchant-name');                const productId = cardLink.getAttribute('data-analytics-id');                const price = parseFloat(cardLink.getAttribute('data-price')) || null;                const prevPriceStr = cardLink.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = cardLink.getAttribute('data-original-link');                const rewrittenLink = cardLink.getAttribute('href');                const revenueId = cardLink.getAttribute('data-revenue-id');                const index = parseInt(cardLink.getAttribute('data-index'), 10) || 0;                const inStock = cardLink.getAttribute('data-in-stock') === 'true';                const totalText = cardLink.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: cardLink.getAttribute('data-model-id') || null,                    matchId: cardLink.getAttribute('data-match-id') || null,                    brand: cardLink.getAttribute('data-model-brand') || null,                    parent: cardLink.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: cardLink.getAttribute('data-merchant-id') || null,                    network: cardLink.getAttribute('data-merchant-network') || null,                    url: cardLink.getAttribute('data-merchant-url') || null,                    name: merchantName                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: normalizeCurrency(this.escapeHTML(cardLink.getAttribute('data-currency') || '$'))                };                if (dealCard) {                  trackDealClick(trackingParams);                } else {                  trackViewSimilarClick(trackingParams);                }              }              const couponsBtn = e.target.closest('[data-action="coupons-click"]');              if (couponsBtn) {                trackElementInteraction({                  id: 'product-card-show-coupons',                  name: 'Coupons',                  label: `Product card coupons: ${couponsBtn.getAttribute('data-merchant')}`                });              }            });          }          this.setupScrollListeners();        }        setupScrollListeners() {          const containers = [             this.root.querySelector('.tg-df-carousel-roundels'),             this.root.querySelector('.tg-df-carousel-filters-wrap'),             this.root.querySelector('#tg-df-grid')          ];                    containers.forEach(container => {             if (!container) return;                          const checkScroll = () => {                if (!container.parentElement) return;                const leftBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-left');                const rightBtn = container.parentElement.querySelector('.tg-df-carousel-scroll-right');                                if (leftBtn) {                   if (container.scrollLeft <= 5) leftBtn.style.display = 'none';                   else leftBtn.style.display = 'flex';                }                                if (rightBtn) {                   if (container.scrollWidth <= container.clientWidth) {                       rightBtn.style.display = 'none';                   } else if (container.scrollLeft >= container.scrollWidth - container.clientWidth - 5) {                       rightBtn.style.display = 'none';                   } else {                       rightBtn.style.display = 'flex';                   }                }             };                          container.addEventListener('scroll', checkScroll);             checkScroll();                          window.addEventListener('resize', checkScroll);                          const observer = new MutationObserver(checkScroll);             observer.observe(container, { childList: true, subtree: true, characterData: false });          });        }        get widgetTypeName() {          const mode = this.viewModeSelect ? this.viewModeSelect.value : (this.viewModeOverride || 'auto');          switch(mode) {              case 'carousel': return 'Carousel';              case 'savings_squad': return 'Savings Squad';              case 'grid': return 'Grid';              case 'row': return 'Row';              default: return 'Auto Collection';          }        }        getRowsLimit() {          if (this.rowsSelect && this.rowsSelect.value) return parseInt(this.rowsSelect.value, 10);          let configSource = window.location.search;          if (this.hostContainer && this.hostContainer.hasAttribute('data-widget-config')) {             configSource = this.hostContainer.getAttribute('data-widget-config');          } else if (typeof window !== 'undefined' && window.__WIDGET_CONFIG__) {             configSource = window.__WIDGET_CONFIG__;          }          const params = new URLSearchParams(configSource);          if (params.has('rows')) return parseInt(params.get('rows'), 10) || 12;          return 12;        }        getAreaCode() {          if (this.regionSelect && this.regionSelect.value) {            if (this.regionSelect.value === 'auto') return null;            return this.regionSelect.value;          }          let area = null;          try {            const locale = window.navigator.language || window.navigator.userLanguage;            if (locale && locale.includes('-')) {              area = locale.split('-')[1].toUpperCase();            } else if (locale && locale.length === 2) {              if (locale.toUpperCase() === 'EN') { area = 'US'; }              else { area = locale.toUpperCase(); }            }          } catch (e) { /* Ignore */ }                    // Map to known valid options or fallback to US          const valid = ['US', 'GB', 'CA', 'AU', 'DE', 'FR', 'IT'];          if (area === 'UK') area = 'GB';          if (valid.includes(area)) {             return area;          }          return 'US';        }                async loadCarouselSpreadsheet() {          try {              const parseCSVRow = (str) => {                  let result = [], cur = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (inQuotes) {                          if (char === '"') {                              if (str[i + 1] === '"') { cur += '"'; i++; }                              else { inQuotes = false; }                          } else { cur += char; }                      } else {                          if (char === '"') { inQuotes = true; }                          else if (char === ',') { result.push(cur); cur = ''; }                          else { cur += char; }                      }                  }                  result.push(cur); return result;              };              const parseCSV = (str) => {                  const rows = []; let curRow = '', inQuotes = false;                  for (let i = 0; i < str.length; i++) {                      let char = str[i];                      if (char === '"') inQuotes = !inQuotes;                      if ((char === '\n' || char === '\r') && !inQuotes) {                          if (char === '\r' && str[i+1] === '\n') i++;                          if (curRow) rows.push(parseCSVRow(curRow));                          curRow = '';                      } else { curRow += char; }                  }                  if (curRow) rows.push(parseCSVRow(curRow));                  return rows;              };              const preloadedCSV = decodeURIComponent(escape(atob("LCwxLDIsMyw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNQ0KUm91bmRlbCB0ZXh0LEFsbCxUVnMsRm9vdHdlYXIsQXBwYXJlbCxNYXR0cmVzZXMsQXBwbGlhbmNlcyxXZWFyYWJsZSB0ZWNoLEhlYWRwaG9uZXMsU21hcnQgSG9tZSxTcGVha2VycyxMYXB0b3BzLFRhYmxldHMsQ29tcHV0aW5nLFBob25lcyxHYW1pbmcsTGVnbw0KUm91bmRlbCBpbWFnZSxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL2FpLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL3R2cy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvN2IzYTIyNGIwNzk2M2M2MjdiNmI5MDliZDc4MzM4MzZlMDJmZjgxOS5qcGcud2VicCxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy84NGRhYzVkNDhlZDJkNDQ4NTU5ZWJhNjdhY2U4MzE0Y2M2N2NjZDk0LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vc2hvcC1hc3NldHMvY2Fyb3VzZWwvbWF0dHJlc3Nlcy5wbmcsaHR0cHM6Ly9pbWFnZXMuZmllLmZ1dHVyZWNkbi5uZXQvcHJvZHVjdHMvNzY4ZTk3Y2ViMDcxODAxZmFlMjA5MTBkMDgyMGIxNmY3NDdhZjkzOS5qcGcud2VicCxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL3dlbGxuZXNzLnBuZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL2hlYWRwaG9uZXMuanBnLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzg5NTM1YmVlYmUyMGRiYmQ0YTM0NmQ2ZDZiZGZlOTFkOGE4ODRhMjEuanBnLndlYnAsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9zaG9wLWFzc2V0cy9jYXJvdXNlbC9hdWRpby5qcGcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9zaG9wLWFzc2V0cy9jYXJvdXNlbC9sYXB0b3BzLmpwZyxodHRwczovL2ltYWdlcy5maWUuZnV0dXJlY2RuLm5ldC9wcm9kdWN0cy8yMzk3NTY0ZWQ3YTVmZjk0N2U5YjZiMzBlNTRmNDc0OTRiODQxZjg5LmpwZy53ZWJwLGh0dHBzOi8vd3d3LnRvbXNndWlkZS5jb20vc2hvcC1hc3NldHMvY2Fyb3VzZWwvY29tcHV0aW5nLmpwZyxodHRwczovL3d3dy50b21zZ3VpZGUuY29tL3Nob3AtYXNzZXRzL2Nhcm91c2VsL3Bob25lcy5wbmcsaHR0cHM6Ly93d3cudG9tc2d1aWRlLmNvbS9zaG9wLWFzc2V0cy9jYXJvdXNlbC9nYW1pbmcucG5nLGh0dHBzOi8vaW1hZ2VzLmZpZS5mdXR1cmVjZG4ubmV0L3Byb2R1Y3RzLzRmNmM2MjFjYWMwYmMxYTg1ZDU5M2UzNTk0YmE1YjM0OWVmZmQyOTIuanBnLndlYnANClNlYXJjaCBRdWVyeSxFdmVyeXRoaW5nLFRlbGV2aXNpb25zLCJTbmVha2VycywgcnVubmluZyBzaG9lcywgc2FuZGFscyIsQ2xvdGhpbmcsTWF0dHJlc3NlcyxIb21lIEFwcGxpYW5jZXMsV2VhcmFibGVzICYgRml0bmVzcyBUZWNoLEhlYWRwaG9uZXMsSG9tZSBUZWNoLFNwZWFrZXJzLExhcHRvcHMsVGFibGV0cyxDb21wdXRpbmcsUGhvbmVzLEdhbWluZyxDb25zdHJ1Y3Rpb24gVG95cw0KRGlzY291bnQgQW1vdW50LG1pbiA1JSxtaW4gMTAlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUsbWluIDUlLG1pbiA1JSxtaW4gNSUNClByaWNlIFJhbmdlLCwsLCxtaW4gJDQwMCwsLCxtaW4gJDI1LCxtaW4gJDMwMCwsLG1pbiAkMTAwLCwNCkJyYW5kIFNlbGVjdGlvbiwsLCwsLCwsLCwsLCwsLCwNCkZpbHRlciBidXR0b25zLCwsLCwsLCwsLCwsLCwsLA0KMSxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMsTGlnaHRuaW5nIGRlYWxzLExpZ2h0bmluZyBkZWFscyxMaWdodG5pbmcgZGVhbHMNCjIsQW1hem9uIGRlYWxzLFVuZGVyICQxMDAwLDUwJSBvZmYsQWRpZGFzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsNTAlIG9mZixBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscyxBbWF6b24gZGVhbHMsQW1hem9uIGRlYWxzLEFtYXpvbiBkZWFscw0KMyxPdmVyICQ0MDAsVW5kZXIgJDUwMCxIb2thLE5pa2UsU2FhdHZhLE5pbmphLDQwJSBvZmYsSkxhYiwsSkJMLERlbGwsLEFzdXMsQXBwbGUsQ29uc29sZXMsU3RhciBXYXJzDQo0LFVuZGVyICQxMDAwLDUwJSBvZmYsU2tlY2hlcnMsVW5kZXIgQXJtb3VyLEhlbGl4LFNoYXJrLEdhcm1pbixBbmtlciBTb3VuZGNvcmUsUmluZyxTb25vcyxBcHBsZSxBcHBsZSxUUC1saW5rLFNhbXN1bmcsQWNjZXNzb3JpZXMsVW5kZXIgJDI1DQo1LFVuZGVyICQ1MDAsTEcsQXNpY3MsQ29sdW1iaWEsRHJlYW1DbG91ZCxLZXVyaWcsQXBwbGUsU29ueSxHb3ZlZSxUcmliaXQsTGVub3ZvLFNhbXN1bmcsRWVybyxHb29nbGUsR2FtZXMsVW5kZXIgJDUwDQo2LDUwJSBvZmYsU2Ftc3VuZyxOaWtlLFBhdGFnb25pYSxOZWN0YXIsRGUnTG9uZ2hpLEFtYXpmaXQsQXBwbGUsS2FzYSBzbWFydCxTb255LEFsaWVud2FyZSxUQ0wsTmV0Z2VhcixNb3Rvcm9sYSxOaW50ZW5kbyxCb3RhbmljYWxzDQo3LEFtYXpvbixIaXNlbnNlLE5ldyBCYWxhbmNlLEFyYyd0ZXJ5eCxUZW1wdXItcGVkaWMsRHlzb24sRml0Yml0LEJlYXRzLFBoaWxpcHMgSHVlLEFua2VyLEFjZXIsT25lUGx1cyxEZWxsLE9uZVBsdXMsU29ueSxEaXNuZXkNCjgsQXBwbGUsVENMLEFkaWRhcyxDYXJoYXJ0dCxCZWFyLEJpc3NlbGwsU2Ftc3VuZyxFYXJmdW4sQmxpbmssQmVhdHMsTVNJLE1pY3Jvc29mdCxBY2VyLE5vdGhpbmcsWGJveCxNYXJ2ZWwNCjksLFNvbnksU2F1Y29ueSxUaGUgTm9ydGggRmFjZSxTaWVuYSxOdXRyaWJ1bGxldCxPdXJhLFNhbXN1bmcsR29vZ2xlIE5lc3QgLE1hcnNoYWxsLFNhbXN1bmcsTGVub3ZvLExlbm92bywsLFBva2Vtb24NCjEwLCxSb2t1LEJpcmtlbnN0b2NrLENSWiBZb2dhLFdpbmtCZWRzLEJsYWNrIGFuZCBEZWNrZXIsUmluZ2Nvbm4sQ01GLEV1ZnksU2Ftc3VuZyxNaWNyb3NvZnQsUmVNYXJrYWJsZSxBbGllbndhcmUsLCwNCjExLCwsQnJvb2tzLFRoZSBHeW0gUGVvcGxlLEJyb29rbHluIGJlZGRpbmcsTmVzcHJlc3NvLCwxTW9yZSxBcmxvLCxSYXplciwsQ29yc2FpciwsLA0KMTIsLCxDcm9jcywsRWlnaHQgU2xlZXAsQ3Vpc2luYXJ0LCxKQkwsLCwsLEhQLCwsDQpOb3RlcywsLCwsLCwsLCwsLCwsLCwNCiwsIlByaW9yaXRpc2UgYmlnZ2VzdCAlLyQgZGlzY291bnQsIFR2cyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiB0aGUgbW9zdCBwb3B1bGFyIGV2ZW4gaWYgdGhleSBhcmUgc3RpbGwgZXhwZW5zaXZlIiwiTm8gcGF0dGVybiB0byBwcmljaW5nL2Rpc2NvdW50LCByZWFkZXJzIG1haW5seSBzaG9wIGJ5IGJyYW5kL3JlY29nbmlzYWJsZSBzaG9lcyIsIk5vIHBhdHRlcm4gdG8gcHJpY2luZy9kaXNjb3VudCwgcmVhZGVycyBtYWlubHkgc2hvcCBieSBicmFuZCIsIkEgbGFiZWwgd2lsbCBkZWZpbml0ZWx5IGhlbHAgaGVyZSBlLmcuIGJlc3QgZm9yIHNpZGUgc2xlZXBlciwgYmVzdCBtZW1vcnkgZm9hbSIsIkFwcGxpYW5jZXMgaXMgYSBiaWcgY2F0ZWdvcnksIGlzIGl0IHBvc3NpYmxlIHRvIHNwbGl0IGludG8ga2l0Y2hlbiBhcHBsaWFuY2VzLCBmbG9vcmNhcmUsIGFpciBoZWFsdGgvY29vbGluZz8gT3Igc2ltaWxhciIsIkZvY3VzIG9uIHZhbHVlIGZvciBtb25leSwgR2FybWlucyB3aXRoIH41MCUgb2ZmIGhhdmUgYmVlbiBwb3B1bGFyIGV2ZW4gdGhvdWdoIHRoZXkgYXJlIHN0aWxsICQ1MDAiLCwsLCxJbmNsdWRlIEtpbmRsZXMsSSB3b3VsZCBpbmNsdWRlIHdpZmkgcm91dGVycyBoZXJlIGluc3RlYWQgb2Ygc21hcnQgaG9tZSxDYW4gd2Ugc3VyZmFjZSBwaG9uZSBwcm92aWRlciBkZWFscz8gVC1tb2JpbGUgYW5kIHZlcml6b24gd291bGQgbWFrZSBhIGxvdCBtb3JlIG1vbmV5IHRoYW4gQW1hem9uLCwNCiwsaGF2aW5nIGEgJ2Jlc3QgZm9yJyBsYWJlbCB3b3VsZCBiZSBoZWxwZnVsIGUuZy4gYmVzdCBmb3IgYnJpZ2h0IHJvb20sQ2FuIHdlIHN0b3Aga2lkcyBzaG9lcyBmcm9tIHB1bGxpbmcgdGhyb3VnaD8sIldpbGwgdGhpcyBpbmNsdWRlIGFjY2Vzc29yaWVzIGUuZy4gY2FwcywgYmFncywgaWYgc28gbWFrZSBzdXJlIHRoZXNlIGFyZSBtaXhlZCB0aHJvdWdob3V0IGNsb3RoaW5nIGRlYWxzIixXaWxsIHRoaXMgaW5jbHVkZSB0b3BwZXJzIGFuZCBwaWxsb3dzPyBTZWVpbmcgbW9yZSBtb21lbnR1bSB3aXRoIHRoaXMgY2F0ZWdvcnkgcmVjZW50bHkgc28gYSBiZWRkaW5nIHRhYiBtaWdodCB3b3JrLCwiTmVlZCB0byBtYWtlIHN1cmUgYmFuZHMsIHNjcmVlbiBwcm90ZWN0b3JzIGV0Yy4gZG9uJ3QgcHVsbCBpbnRvIGhlcmUiLCwsLCwsLCwsDQosLCJQcmlvcml0aXNlIDY1JycgYW5kIDU1JyBpbmNoIFRWcywgdGhlbiBiaWdnZXIgc2NyZWVucyBiZWZvcmUgdGhlIHNtYWxsZXIgc2l6ZXMiLCwsUXVlZW4gaXMgdGhlIG1vc3QgcG9wdWxhciBzaXplIGluIHRoZSBVUyAtIHByaW9yaXRpc2UgZGVhbHMgZm9yIHRoaXMgc2l6ZSwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpDYXRlZ29yaWVzIHRvIGNvbnNpZGVyLCxQcm9kdWN0cyBpbmNsdWRlZCwsLCwsLCwsLCwsLCwsDQpVbmRlciAkNTA/LCxBaXIgdGFncywsLCwsLCwsLCwsLCwsDQosLFBvcnRhYmxlIGNoYXJnZXJzL3dpcmVsZXNzIGNoYXJnZXJzLCwsLCwsLCwsLCwsLCwNCiwsIldhdGVyIGJvdHRsZXMgKHN0YW5sZXlzLCBPd2FsYSwgSHlkcm8gZmxhc2ssIFlldGkpIiwsLCwsLCwsLCwsLCwsDQosLEhhbmQgaGVsZCBmYW5zLCwsLCwsLCwsLCwsLCwNCiwsLCwsLCwsLCwsLCwsLCwNCmhvbWUgb2ZmaWNlLCxvZmZpY2UgY2hhaXJzLCwsLCwsLCwsLCwsLCwNCiwsc3RhbmRpbmcgZGVza3MsLCwsLCwsLCwsLCwsLA0KLCxtb25pdG9ycywsLCwsLCwsLCwsLCwsDQosLEtleWJvYXJkcywsLCwsLCwsLCwsLCwsDQosLGRvY2tpbmcgc3RhdGlvbiwsLCwsLCwsLCwsLCwsDQosLCwsLCwsLCwsLCwsLCwsDQpHYW1pbmcsLENvbnNvbGVzLCwsLCwsLCwsLCwsLCwNCiwsQWNjZXNzb3JpZXMsLCwsLCwsLCwsLCwsLA0KLCxHYW1lcywsLCwsLCwsLCwsLCwsDQosLENvdWxkIGluY2x1ZGUgTGVnbz8sLCwsLCwsLCwsLCwsLA==")));              const text = preloadedCSV;              const parsed = parseCSV(text);                            const rowsByName = {};              let filterStart = -1;              parsed.forEach((rc, i) => {                 if (rc && rc.length > 0 && rc[0]) rowsByName[rc[0]] = rc;                 if (rc && rc.length > 0 && rc[0] === 'Filter buttons') filterStart = i;              });                            const cols = [];              if(rowsByName['Roundel text']) {                const headerRow = rowsByName['Roundel text'];                for(let col = 1; col < headerRow.length; col++) {                   let label = headerRow[col];                   if (!label) continue;                                      let q = rowsByName['Search Query'] && rowsByName['Search Query'][col] ? rowsByName['Search Query'][col] : '';                   let img = rowsByName['Roundel image'] && rowsByName['Roundel image'][col] ? rowsByName['Roundel image'][col] : '';                   let ds = rowsByName['Discount Amount'] && rowsByName['Discount Amount'][col] ? rowsByName['Discount Amount'][col] : '';                   let pr = rowsByName['Price Range'] && rowsByName['Price Range'][col] ? rowsByName['Price Range'][col] : '';                   let rt = rowsByName['Retailer'] && rowsByName['Retailer'][col] ? rowsByName['Retailer'][col] : '';                   let ot = rowsByName['Offer Type'] && rowsByName['Offer Type'][col] ? rowsByName['Offer Type'][col] : '';                                      let filters = [];                   if(filterStart > 0) {                     for(let r = filterStart + 1; r < parsed.length; r++) {                         if(!parsed[r] || parsed[r][0] === 'Notes' || parsed[r][0] === 'Categories to consider') break;                         let f = parsed[r][col];                         if(f) filters.push(f);                     }                   }                   cols.push({ label, img, q, ds, pr, rt, ot, filters });                }              }              this.carouselData = cols;              if (this.carouselData && this.carouselData.length > 0) {                 const isMatched = this.carouselData.some(c => c.q === this.currentQuery || c.label === this.currentQuery);                 if (!isMatched) {                    const first = this.carouselData[0];                    this.currentQuery = first.q || first.label;                    if (this.priceFilter) this.priceFilter.value = 'all';                    if (this.customPriceMin) this.customPriceMin.value = '';                    if (this.customPriceMax) this.customPriceMax.value = '';                    let dPr = first.pr || 'all';                    if (typeof dPr === 'string' && dPr !== 'all') {                       let prLower = dPr.toLowerCase();                       if (prLower.includes('min') || prLower.includes('over')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else if (prLower.includes('max') || prLower.includes('under')) {                          let m = dPr.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       }                    }                    let dAm = '0';                    if(first.ds && typeof first.ds === 'string') {                       let m = first.ds.match(/(\d+)/);                       if(m) dAm = m[1];                    }                    if (this.discountFilter) this.discountFilter.value = dAm;                    if (this.offerTypeSelect) this.offerTypeSelect.value = first.ot || '';                    if (this.retailerSelect) this.retailerSelect.value = first.rt || '';                    this.selectedBrands = [];                    if (this.brandDropdown) {                        const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                        chks.forEach(chk => chk.checked = false);                    }                    if (this.searchInput) this.searchInput.value = this.currentQuery;                 }              }              this.renderCarouselUI();          } catch(e){ console.warn(e); }        }                renderCarouselUI() {           const roundelWrapper = this.root.querySelector('.tg-df-carousel-roundels');           if(!roundelWrapper || !this.carouselData) return;                      let html = '';           this.carouselData.forEach(r => {              const q = r.q || r.label;              const isActive = (this.currentQuery === q || this.currentQuery === r.label) ? 'active' : '';              const imgHtml = r.img ? `\x3Cimg src="${r.img}" alt="${r.label}" />` : `\x3Csvg width="32" height="32" fill="#1F69FF" viewBox="0 0 24 24">\x3Cpath d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/>\x3C/svg>`;              html += `                \x3Cdiv class="tg-df-roundel tg-df-carousel-cat ${isActive}" data-label="${this.escapeHTML(r.label)}">                  \x3Cdiv class="tg-df-roundel-img-box">${imgHtml}\x3C/div>                  \x3Cspan class="tg-df-roundel-label">${this.escapeHTML(r.label)}\x3C/span>                \x3C/div>              `;           });           roundelWrapper.innerHTML = html;                      // Rebind clicks           const roundels = this.root.querySelectorAll('.tg-df-carousel-cat');           roundels.forEach(rNode => {             rNode.addEventListener('click', () => {                const r = this.carouselData.find(c => c.label === rNode.getAttribute('data-label'));                 if(!r) return;                                  if (typeof trackHawkEvent !== 'undefined') {                     trackHawkEvent({                         clickType: "CC",                         widgetId: this.widgetId,                         productCategoryName: "deals",                         zeroBasedProductIndexOrNull: null,                         totalDealsOrProducts: null,                         areaClicked: "Category Roundel",                         revenueId: this.revenueId,                         isoCurrencyCode: typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD',                         queryName: r.label,                         widgetTypeName: this.widgetTypeName                     });                 }                this.currentQuery = r.q || r.label;                const labelTitle = this.root.querySelector('#tg-df-carousel-title-label');                if (labelTitle) labelTitle.textContent = 'Best ' + this.currentQuery;                if (this.priceFilter) this.priceFilter.value = 'all';                if (this.customPriceMin) this.customPriceMin.value = '';                if (this.customPriceMax) this.customPriceMax.value = '';                let dPr = r.pr || 'all';                if (typeof dPr === 'string' && dPr !== 'all') {                   let prLower = dPr.toLowerCase();                   if (prLower.includes('min') || prLower.includes('over')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMin) this.customPriceMin.value = m[1];                   } else if (prLower.includes('max') || prLower.includes('under')) {                      let m = dPr.match(/(\d+)/);                      if (m && this.customPriceMax) this.customPriceMax.value = m[1];                   }                }                                let discountAmount = '0';                if(r.ds && typeof r.ds === 'string') {                   let m = r.ds.match(/(\d+)/);                   if(m) discountAmount = m[1];                }                if (this.discountFilter) this.discountFilter.value = discountAmount;                if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                                // Clear brands                    this.selectedBrands = [];                    if (this.brandDropdown) {                    const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                    chks.forEach(chk => chk.checked = false);                }                                if (this.searchInput) this.searchInput.value = this.currentQuery;                                roundels.forEach(ro => ro.classList.remove('active'));                if (rNode) rNode.classList.add('active');                                this.renderCarouselFilters(r);                this.fetchDeals(this.currentQuery);             });           });                      // Auto-highlight active           const activeR = this.carouselData.find(c => c.q === this.currentQuery || c.label === this.currentQuery);           if(activeR) this.renderCarouselFilters(activeR);        }                renderCarouselFilters(r) {           const filtersWrap = this.root.querySelector('.tg-df-carousel-filters-wrap');           if(!filtersWrap) return;                      let html = `\x3Cbutton class="tg-df-carousel-filter-btn" data-type="all">All\x3C/button>`;                      r.filters.forEach(f => {              let fL = f.toLowerCase();              let icon = '';              let logic = `data-type="custom" data-v="${this.escapeHTML(f)}"`;              if (fL === 'amazon deals' || fL === 'prime deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/fwoVXvL79turN3Ph535m38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/u75QjVpt3w2EsMimJiRo38-600-100.png" class="active-img" alt="" /> Prime deals\x3C/button>`;              } else if (fL === 'lightning deals') {                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>\x3Cimg src="https://cdn.mos.cms.futurecdn.net/HqAui7w97ft2NPqBtQ5r38-600-100.png" class="inactive-img" alt="" />\x3Cimg src="https://cdn.mos.cms.futurecdn.net/yWPQ5yyQRhUwVKzGwYbh38-600-100.png" class="active-img" alt="" /> Lightning deals\x3C/button>`;              } else {                 if (fL.includes('lightning')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-zap">\x3Cpolygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2">\x3C/polygon>\x3C/svg>`;                 } else if (fL.includes('% off')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-tag">\x3Cpath d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z">\x3C/path>\x3Ccircle cx="7.5" cy="7.5" r=".5" fill="currentColor">\x3C/circle>\x3C/svg>`;                 } else if (fL.includes('under') || fL.includes('min ')) {                    icon = `\x3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-badge-dollar-sign">\x3Cpath d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z">\x3C/path>\x3Cpath d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8">\x3C/path>\x3Cpath d="M12 18V6">\x3C/path>\x3C/svg>`;                 }                 html += `\x3Cbutton class="tg-df-carousel-filter-btn" ${logic}>${icon} ${this.escapeHTML(f)}\x3C/button>`;              }           });                      filtersWrap.innerHTML = html;                      const btns = filtersWrap.querySelectorAll('button');           btns.forEach(b => {             b.addEventListener('click', () => {                const type = b.getAttribute('data-type');                if (type === 'custom') {                   const v = b.getAttribute('data-v');                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: `filter-custom-${(v||'').toLowerCase().replace(/[^a-z0-9]+/g, '-')}`, name: 'Custom Filter', label: v });                }                if (type === 'all') {                   if (typeof trackElementInteraction === 'function') trackElementInteraction({ id: 'filter-clear-all', name: 'Clear all', label: 'Clear all filters' });                   // reset everything                   btns.forEach(btn => btn.classList.remove('active'));                   b.classList.add('active');                                      // Reset prices                   if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   if (this.brandDropdown) {                     const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                     chks.forEach(chk => chk.checked = false);                   }                } else {                   const v = b.getAttribute('data-v');                   const fL = v.toLowerCase();                                      let mapRet = ['amazon', 'walmart', 'best buy', 'target', 'john lewis', 'currys', 'argos'];                   const getCategory = (s) => {                      if (s === 'lightning deals' || s === 'amazon deals' || s === 'prime deals') return 'offer';                      if (s.includes('% off')) return 'discount';                      if (s.includes('under') || s.includes('over') || s.includes('min') || s.includes('max')) return 'price';                      if (mapRet.includes(s)) return 'retailer';                      return 'brand';                   };                   const cat = getCategory(fL);                   const wasActive = b.classList.contains('active');                   if (cat !== 'brand') {                      btns.forEach(btn => {                          if (btn === b) return;                          if (btn.getAttribute('data-type') === 'all') return;                          const bV = btn.getAttribute('data-v');                          if (!bV) return;                          if (getCategory(bV.toLowerCase()) === cat) btn.classList.remove('active');                      });                   }                   if (wasActive) b.classList.remove('active');                   else b.classList.add('active');                   let anyActive = Array.from(btns).some(btn => btn !== btns[0] && btn.classList.contains('active'));                   if (!anyActive) {                       btns[0].click();                       return;                   } else {                       btns[0].classList.remove('active');                   }                                      if (this.priceFilter) this.priceFilter.value = 'all';                   if (this.customPriceMin) this.customPriceMin.value = '';                   if (this.customPriceMax) this.customPriceMax.value = '';                   let dPr = r.pr || 'all';                   if (typeof dPr === 'string' && dPr !== 'all') {                      let prLower = dPr.toLowerCase();                      if (prLower.includes('min') || prLower.includes('over')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMin) this.customPriceMin.value = m[1];                      } else if (prLower.includes('max') || prLower.includes('under')) {                         let m = dPr.match(/(\d+)/);                         if (m && this.customPriceMax) this.customPriceMax.value = m[1];                      }                   }                                      let discountAmount = '0';                   if(r.ds && typeof r.ds === 'string') {                      let m = r.ds.match(/(\d+)/);                      if(m) discountAmount = m[1];                   }                   if (this.discountFilter) this.discountFilter.value = discountAmount;                   if (this.offerTypeSelect) this.offerTypeSelect.value = r.ot || '';                   if (this.retailerSelect) this.retailerSelect.value = r.rt || '';                   this.selectedBrands = [];                   btns.forEach(btn => {                       if (!btn.classList.contains('active') || btn.getAttribute('data-type') === 'all') return;                       const vv = btn.getAttribute('data-v');                       const vl = vv.toLowerCase();                                              if (vl === 'lightning deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_lightning';                       } else if (vl === 'amazon deals' || vl === 'prime deals') {                          if (this.offerTypeSelect) this.offerTypeSelect.value = 'amazon_prime';                       } else if (vl.includes('% off')) {                          let m = vl.match(/(\d+)%/);                          if (m && this.discountFilter) this.discountFilter.value = m[1];                       } else if (vl.includes('under') || vl.includes('max')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMax) this.customPriceMax.value = m[1];                       } else if (vl.includes('min') || vl.includes('over')) {                          let m = vl.match(/(\d+)/);                          if (m && this.customPriceMin) this.customPriceMin.value = m[1];                       } else {                          let foundR = mapRet.find(x => x === vl);                          if (foundR) {                             let realR = ['Amazon', 'Walmart', 'Best Buy', 'Target', 'John Lewis', 'Currys', 'Argos'].find(x => x.toLowerCase() === vl);                             if (this.retailerSelect) this.retailerSelect.value = realR;                          } else {                             this.selectedBrands.push(vv);                          }                       }                   });                                      if (this.brandDropdown) {                       const chks = this.brandDropdown.querySelectorAll('.tg-df-brand-chk');                       chks.forEach(c => c.checked = this.selectedBrands.includes(c.value));                   }                                      if (r.pr && typeof r.pr === 'string') {                       let prL = r.pr.toLowerCase();                       if (prL.includes('under $')) {                           let m = prL.match(/under \$(\d+)/i);                           if (m && this.customPriceMax && !this.customPriceMax.value) this.customPriceMax.value = m[1];                       }                   }                }                                this.fetchDeals(this.currentQuery);             });           });                      // default to highlighting first           btns[0].classList.add('active');        }async fetchDeals(query, append = false) {          if (!append) {             this.showLoading();             this.deals = [];             this.displayLimit = this.getRowsLimit();          } else {             this.displayLimit += this.getRowsLimit();          }                    try {            if (this.getViewMode() === 'savings_squad') {               await this.fetchSavingsSquad(append);            } else {               if (this.isBroadQuery(query)) {                 await this.fetchAdviserDeals(query, append);               } else {                 await this.fetchHawkDeals(query, append);                 if (this.deals.length === 0) {                   await this.fetchAdviserDeals(query, append);                 }               }            }          } catch (error) {            console.warn("[Tom's Guide Widget] Fetch error:", error);            this.showError();          }        }        async fetchSavingsSquad() {          let topArticles = this.airedaleArticles;          if (!topArticles) {            const airedaleUrl = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`;            let res;            try {               res = await fetch(airedaleUrl);            } catch(e) {               try { res = await fetch(`https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50`); } catch (err) { console.warn("Fallback fetch failed", err); return; }            }            if (!res.ok) throw new Error('Airedale API Error');            const articles = await res.json();            topArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);            this.airedaleArticles = topArticles;                        let tagCounts = {};            topArticles.forEach((a) => {              let articleTags = new Set();              if (a.articlecategory && Array.isArray(a.articlecategory)) {                 a.articlecategory.forEach((t) => articleTags.add(t));              }              articleTags.forEach(t => {                 tagCounts[t] = (tagCounts[t] || 0) + 1;              });            });                        this.airedaleTags = Object.keys(tagCounts).sort((a, b) => tagCounts[b] - tagCounts[a]);            this.airedaleTagCounts = tagCounts;          }                    let targetArticles = topArticles;          if (this.activeDealTag) {             const cleanTag = this.activeDealTag.toLowerCase().replace(/&/g, '').replace(/[^a-z0-9]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');             const encodedTag = encodeURIComponent(cleanTag);             const url = `https://airedale.futurecdn.net/feeds/feed_1776420579726.json?site=tomsguide&articleType=deals&limit=50&articleCategoryHandle=${encodedTag}`;             try {                const res = await fetch(url);                if (res.ok) {                   const articles = await res.json();                   targetArticles = Array.isArray(articles) ? articles.slice(0, 50) : ((articles.data && Array.isArray(articles.data)) ? articles.data.slice(0, 50) : []);                }             } catch(e) {                console.warn("Failed to fetch by activeDealTag", e);             }          }          let extractedDeals = [];          let dynamicBrandsCounts = {};                    targetArticles.forEach((article) => {             if (!article.articlepage) return;                          let pageData = [];             try {                pageData = JSON.parse(article.articlepage[0]);             } catch(e){ console.warn(e); }                          const savingsSquad = pageData.filter((p) => p.type === 'deal' || p.type === 'featured-product');                          savingsSquad.forEach((block, idx) => {                const data = block.data || {};                const isFeatured = block.type === 'featured-product';                                const link = data.link || {};                const priceObj = data.price || {};                const image = data.image || {};                                if (data.brand) {                   data.brand = data.brand.replace(/^\d+\.\s*/, '').trim();                   dynamicBrandsCounts[data.brand] = (dynamicBrandsCounts[data.brand] || 0) + 1;                }                const externalUrl = isFeatured ? data.url : (link.href || null);                let summaryTitle = isFeatured ? (data.name || data.brand) : (data.productName || link.label || article.articlename);                let description = isFeatured ? (data.strapline || '') : (data.text || '');                                if (!isFeatured && !data.productName && data.text) {                   const brSplit = data.text.split(new RegExp('\x3Cbr\\s*\\/?\\x3E', 'i'));                   if (brSplit.length > 1) {                     summaryTitle = brSplit[0].replace(/<[^>]+>/g, '').trim();                     description = brSplit.slice(1).join(' ').replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();                   } else {                     const match = data.text.match(/\x3Cstrong>(.*?)<\/strong>/);                     if (match) {                       summaryTitle = match[1].replace(/<[^>]+>/g, '').trim();                       if (summaryTitle.endsWith(':')) summaryTitle = summaryTitle.slice(0, -1);                     }                   }                }                                let imageUrl = isFeatured ? image.mos : (image.src || null);                if (imageUrl && imageUrl.startsWith('//')) imageUrl = 'https:' + imageUrl;                                description = description.replace(/<br\s*\/?>/gi, ' ').replace(/<\/?(p|div)[^>]*>/gi, ' ').replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').replace(/View Deal$/i, '').trim();                                let merchantName = data.retailer || '';                if (!merchantName && externalUrl) {                   try {                     merchantName = new URL(externalUrl).hostname.replace('www.', '').split('.')[0];                     merchantName = merchantName.charAt(0).toUpperCase() + merchantName.slice(1);                   }catch(e){ console.warn(e); }                }                if (!merchantName) merchantName = 'Retailer';                const q = (this.currentQuery || '').toLowerCase();                const activeTagLogic = (this.activeDealTag || '').toLowerCase();                if (q.length > 2 && q !== activeTagLogic) {                   const searchTarget = `${summaryTitle || ''} ${description || ''}`.toLowerCase();                   if (!searchTarget.includes(q)) return;                }                let rawPrice = 0;                let rawMsrp = 0;                let currencyStr = '$';                if (isFeatured) {                   rawPrice = typeof data.salePrice === 'number' && data.salePrice > 0 ? data.salePrice : (typeof data.price === 'number' ? data.price : 0);                   rawMsrp = typeof data.salePrice === 'number' && typeof data.price === 'number' && data.price > data.salePrice ? data.price : 0;                   currencyStr = data.currency === 'GBP' ? '£' : '$';                } else {                   rawPrice = priceObj.amount ? parseFloat(priceObj.amount) : 0;                   rawMsrp = priceObj.amountWas ? parseFloat(priceObj.amountWas) : 0;                   currencyStr = priceObj.currency === 'GBP' ? '£' : '$';                }                                let savingAmt = 0;                let savingLabel = '';                if (rawPrice > 0 && rawMsrp > rawPrice) {                   savingAmt = parseFloat((rawMsrp - rawPrice).toFixed(2));                   savingLabel = `Save ${currencyStr}${savingAmt}`;                }                                // Apply Brand filter                if (this.selectedBrands && this.selectedBrands.length > 0) {                   const itemBrand = (data.brand || '').toLowerCase();                   const hasMatch = this.selectedBrands.some(sb => sb.toLowerCase() === itemBrand);                   if (!hasMatch) return;                }                // Apply Price filter                let priceFilterVal = null;                const min = this.customPriceMin ? this.customPriceMin.value : '';                const max = this.customPriceMax ? this.customPriceMax.value : '';                if (min || max) {                   priceFilterVal = `${min}_${max}`;                } else if (this.priceFilter && this.priceFilter.value !== 'all') {                   priceFilterVal = this.priceFilter.value;                }                if (priceFilterVal && rawPrice > 0) {                   if (priceFilterVal === 'under50' && rawPrice >= 50) return;                   if (priceFilterVal === 'over50' && rawPrice <= 50) return;                   if (priceFilterVal === 'over30' && rawPrice <= 30) return;                   if (priceFilterVal === 'over500' && rawPrice <= 500) return;                   if (priceFilterVal.includes('_')) {                      const parts = priceFilterVal.split('_');                      const min = parseFloat(parts[0]);                      const max = parseFloat(parts[1]);                      if (!isNaN(min) && rawPrice < min) return;                      if (!isNaN(max) && rawPrice > max) return;                   }                }                // Apply Discount filter                if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {                   const requiredDiscount = parseInt(this.discountFilter.value);                   if (!isNaN(requiredDiscount) && requiredDiscount > 0) {                      if (!rawMsrp || rawMsrp <= rawPrice) return;                      const ratio = Math.round((1 - (rawPrice / rawMsrp)) * 100);                      if (ratio < requiredDiscount) return;                   }                }                                extractedDeals.push({                   id: `airedale-${article.id || Math.random()}-${idx}`,                   url: externalUrl,                   image: imageUrl,                   fallbackImage: imageUrl,                   title: summaryTitle,                   brand: data.brand || '',                   productName: data.productName || '',                   merchant: merchantName,                   rawPrice: rawPrice,                   rawMsrp: rawMsrp,                   price: rawPrice > 0 ? rawPrice.toString() : '',                   msrp: rawMsrp > 0 ? rawMsrp.toString() : '',                   currency: currencyStr,                   isCheckPrice: !rawPrice,                   savingLabel: savingLabel,                   savingType: rawMsrp > rawPrice ? 'amount' : 'none',                   isPrime: false,                   starRating: null,                   description: description,                   text: data.text || ''                });             });          });                    const airedaleBrandsList = Object.keys(dynamicBrandsCounts).map(b => ({              formatted_value: b,              count: dynamicBrandsCounts[b]          })).sort((a,b) => b.count - a.count);                    if (this.getViewMode() === 'savings_squad') {             this.populateBrandDropdown(airedaleBrandsList.slice(0, 15));             if (this.brandFilterWrapper) {                if (airedaleBrandsList.length === 0) {                    this.brandFilterWrapper.style.display = 'none';                } else {                    this.brandFilterWrapper.style.display = 'flex';                }             }          }                    this.deals = extractedDeals;          this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        isBroadQuery(query) {          const q = query.toLowerCase();          const intentModifiers = ['deals', 'best', 'sale', 'under', 'cheap', 'offers', 'discount'];          return intentModifiers.some(term => q.includes(term));        }        async fetchHawkDeals(query, append = false) {          const url = new URL(this.apiUrl);          url.searchParams.append('model_name', query);          const areaCode = this.getAreaCode();          if (areaCode) {            url.searchParams.append('area', areaCode);          }                    if (append && this.deals.length > 0) {            url.searchParams.append('offset', this.deals.length.toString());          }                    if (this.retailerSelect && this.retailerSelect.value) {            url.searchParams.append('filter_merchant_name', this.retailerSelect.value);          }                    if (this.selectedBrands && this.selectedBrands.length > 0) {            url.searchParams.append('filter_label[text_brand]', this.selectedBrands.join(','));          }                    let priceVal = null;          const min = this.customPriceMin ? this.customPriceMin.value : '';          const max = this.customPriceMax ? this.customPriceMax.value : '';          if (min || max) {             priceVal = `${min}_${max}`;          } else if (this.priceFilter && this.priceFilter.value !== 'all') {             priceVal = this.priceFilter.value;          }          if (priceVal) {            if (priceVal === 'under50') {              url.searchParams.append('filter_max_price', '50');            } else if (priceVal === 'over50') {              url.searchParams.append('filter_min_price', '50');            } else if (priceVal === 'over30') {              url.searchParams.append('filter_min_price', '30');            } else if (priceVal === 'over500') {              url.searchParams.append('filter_min_price', '500');            } else if (priceVal.includes('_')) {              const parts = priceVal.split('_');              if (parts[0]) url.searchParams.append('filter_min_price', parts[0]);              if (parts[1]) url.searchParams.append('filter_max_price', parts[1]);            }          }                    if (this.discountFilter && this.discountFilter.value !== 'all' && this.discountFilter.value !== '0') {            const v = parseInt(this.discountFilter.value);            if (!isNaN(v) && v > 0) {              const ratio = (100 - v) / 100;              url.searchParams.append('min_discount_ratio', ratio.toString());            }          }                    if (this.offerTypeSelect && this.offerTypeSelect.value) {            url.searchParams.append('offer', this.offerTypeSelect.value);          }                    url.searchParams.append('filter_product_types', 'deals');                    url.searchParams.append('rows', this.getRowsLimit().toString());          let response;          try {             response = await fetch(url.toString());          } catch(e) {             if (window.location.protocol === 'file:') {                console.warn("[Tom's Guide Widget] fetch from file:// blocked by local CORS policy, falling back to Adviser mock.");                await this.fetchAdviserDeals(query);                return;             }             console.warn("Hawk fetch failed", e);             this.deals = [];             this.render();             return;          }          if (!response.ok) {            throw new Error('Hawk API Response Error');          }          const rawData = await response.json();          // Safely locate data array from potentially wrapped response          let offers = [];          let modelInfoArray = [];                    let brandFilterData = null;          if (rawData && rawData.widget && rawData.widget.data && Array.isArray(rawData.widget.data.filters)) {             brandFilterData = rawData.widget.data.filters.find(f => f.type === 'label_text_brand');          } else if (rawData && rawData.data && Array.isArray(rawData.data.filters)) {             brandFilterData = rawData.data.filters.find(f => f.type === 'label_text_brand');          }          if (brandFilterData && Array.isArray(brandFilterData.values) && brandFilterData.values.length > 0) {             this.populateBrandDropdown(brandFilterData.values);          } else {             if (this.brandFilterWrapper && this.selectedBrands.length === 0) {                this.brandFilterWrapper.style.display = 'none';             }          }                    if (rawData && rawData.widget && rawData.widget.data) {            if (Array.isArray(rawData.widget.data.offers)) offers = rawData.widget.data.offers;            if (rawData.widget.data.model_info && typeof rawData.widget.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.widget.data.model_info) ? rawData.widget.data.model_info : Object.values(rawData.widget.data.model_info);            }          } else if (rawData && rawData.data) {            if (Array.isArray(rawData.data.offers)) offers = rawData.data.offers;            if (rawData.data.model_info && typeof rawData.data.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.data.model_info) ? rawData.data.model_info : Object.values(rawData.data.model_info);            }          } else {            if (Array.isArray(rawData)) offers = rawData;            else if (rawData && Array.isArray(rawData.offers)) offers = rawData.offers;            else if (rawData && rawData.offers && Array.isArray(rawData.offers.offer)) offers = rawData.offers.offer;            else if (rawData && rawData.offers) offers = [].concat(rawData.offers);                        if (rawData && rawData.model_info && typeof rawData.model_info === 'object') {              modelInfoArray = Array.isArray(rawData.model_info) ? rawData.model_info : Object.values(rawData.model_info);            }          }          let modelDetails = {};          modelInfoArray.forEach(m => {            const mId = m.model_id || m.id;            if (mId) {              modelDetails[mId] = {                score: m.score != null ? parseFloat(m.score) : null,                brand: m.brand || null,                parent: (m.parents && Array.isArray(m.parents) && m.parents.length > 0) ? m.parents[0].name : null              };            }          });          offers.forEach(item => {            let data = { ...item };            const mId = data.model_id;            if (mId && modelDetails[mId]) {              data.review_score = modelDetails[mId].score;              data.model_brand = modelDetails[mId].brand;              data.model_parent = modelDetails[mId].parent;            } else {              data.review_score = null;            }                        let itemOffers = [];            if (Array.isArray(item.offers)) itemOffers = item.offers;            else if (Array.isArray(item.offer)) itemOffers = item.offer;            else if (item.offers && typeof item.offers === 'object') itemOffers = [item.offers];            else if (item.offer && typeof item.offer === 'object') itemOffers = [item.offer];            if (itemOffers.length > 0) {              itemOffers.forEach(subItem => {                let subData = { ...item, ...subItem };                const subId = subData.model_id;                if (subId && modelDetails[subId]) {                  subData.review_score = modelDetails[subId].score;                  subData.model_brand = modelDetails[subId].brand;                  subData.model_parent = modelDetails[subId].parent;                } else if (data.review_score != null) {                  subData.review_score = data.review_score;                }                if (subData.merchant && typeof subData.merchant === 'object') {                  subData.merchant_name = subData.merchant.name;                }                this.deals.push(this.extractDealData(subData));              });              return;            }                        if (item.merchant && typeof item.merchant === 'object') {              data.merchant_name = item.merchant.name;            }                        this.deals.push(this.extractDealData(data));          });                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        async fetchAdviserDeals(query) {          // ======================================================================          // TODO: ADVISER API REPLACEMENT          // The code below simulates the Adviser API response using mock data.          // Once the real endpoint is ready, remove getAdviserMockData() and           // perform an actual fetch() request similar to fetchHawkDeals().          // Example:          // const area = this.getAreaCode();          // let apiUrl = `https://your-adviser-api.com/search?q=${query}&area=${area}`;          // if (this.priceFilter && this.priceFilter.value !== 'all') {          //   const val = this.priceFilter.value;          //   if (val === 'under50') apiUrl += '&filter_max_price=50';          //   else if (val === '50_100') apiUrl += '&filter_max_price=100';          //   else if (val === '100_200') apiUrl += '&filter_max_price=200';          //   else if (val === '200_500') apiUrl += '&filter_max_price=500';          // }          // const res = await fetch(apiUrl);          // const rawData = await res.json();          // ======================================================================          // Simulating network latency          await new Promise(resolve => setTimeout(resolve, 400));                    const rawData = this.getAdviserMockData();          let offers = [];                    if (rawData && rawData.data && rawData.data.Get && Array.isArray(rawData.data.Get.Deal)) {            offers = rawData.data.Get.Deal;          }                    // Basic client-side filtering for the mock if we want it to react to the query          const q = query.toLowerCase();          const selectedRetailer = (this.retailerSelect && this.retailerSelect.value) ? this.retailerSelect.value.toLowerCase() : null;                    offers.forEach(item => {            const dataObj = item;                        // Apply retailer filter            const itemRetailer = (dataObj.dataRetailer || '').toLowerCase();            if (selectedRetailer && itemRetailer !== selectedRetailer && !itemRetailer.includes(selectedRetailer)) {              return;            }                        // Apply mock price filter            let price = dataObj.dataDiscountedPrice || 0;            if (typeof price === 'string') {              price = parseFloat(price.replace(/[^0-9.]/g, ''));            }            let priceVal = null;            const min = this.customPriceMin ? this.customPriceMin.value : '';            const max = this.customPriceMax ? this.customPriceMax.value : '';            if (min || max) {               priceVal = `${min}_${max}`;            } else if (this.priceFilter && this.priceFilter.value !== 'all') {               priceVal = this.priceFilter.value;            }            if (priceVal) {              if (priceVal === 'under50' && price >= 50) return;              if (priceVal === 'over50' && price <= 50) return;              if (priceVal === 'over30' && price <= 30) return;              if (priceVal === 'over500' && price <= 500) return;              if (priceVal.includes('_')) {                 const parts = priceVal.split('_');                 if (parts[0] && price < parseFloat(parts[0])) return;                 if (parts[1] && price > parseFloat(parts[1])) return;              }            }                        // Map Adviser schema to our widget's expected schema            const mappedData = {              url: dataObj.linkHREF || dataObj.dataLink || '#',              image: dataObj.imageURL || (dataObj.image && dataObj.image.src) || '',              title: dataObj.dataProduct || (dataObj.product && dataObj.product.name) || 'Product Deal',              merchant: dataObj.dataRetailer || 'Retailer',              price: dataObj.dataDiscountedPrice || 0,              currency: dataObj.dataCurrency === 'USD' ? '$' : (dataObj.dataCurrency || '$'),              msrp: dataObj.dataOriginalPrice || null            };                        const titleLow = mappedData.title.toLowerCase();            const merchLow = mappedData.merchant.toLowerCase();                        // Smarter mock filtering            let isMatch = false;            if (q === '' || this.isBroadQuery(q)) {              isMatch = true;            } else if (titleLow.includes(q) || merchLow.includes(q)) {              isMatch = true;            } else if ((q.includes('laptop') || q.includes('mac') || q.includes('pc')) && (titleLow.includes('macbook') || titleLow.includes('laptop'))) {              isMatch = true;            } else if ((q.includes('tv') || q.includes('television')) && (titleLow.includes('tv') || titleLow.includes('oled') || titleLow.includes('qled'))) {              isMatch = true;            } else if ((q.includes('phone') || q.includes('smartphone')) && (titleLow.includes('galaxy') || titleLow.includes('phone'))) {              isMatch = true;            } else if ((q.match(/watch|fitness|run|shoe/)) && (titleLow.includes('forerunner') || titleLow.includes('saucony') || titleLow.includes('watch'))) {              isMatch = true;            }                        if (isMatch) {               this.deals.push(this.extractDealData(mappedData));            }          });                    let rowLimit = this.getRowsLimit();          // Intentionally omitting the slice here to allow "Load More" to work if the API returns more                    this.sortData();          this.render();          if (typeof trackDealsAppeared !== 'undefined') {             trackDealsAppeared(this.widgetId, this.deals, this.revenueId, typeof this.getAreaCode === 'function' ? (this.getAreaCode() === 'GB' ? 'GBP' : 'USD') : 'USD', this.currentQuery, this.widgetTypeName);          }        }        getAdviserMockData() {          return {            "data": {              "Get": {                "Deal": [                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 300,                    "dataOriginalPrice": 399,                    "dataProduct": "Samsung Galaxy A36",                    "dataRetailer": "Samsung",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/MqDYsukV3JBG54te6dEs7j.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 14,                    "dataOriginalPrice": 24,                    "dataProduct": "Blink Mini",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/3JurmAjHsDa5tPdaHAwEV8.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 59,                    "dataOriginalPrice": 99,                    "dataProduct": "Ring Video Doorbell",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/rAh4uR7AsAsALCCLTXnLNJ.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 10,                    "dataOriginalPrice": 599,                    "dataProduct": "MacBook Neo",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/Lg4Dvg68j9SbB5CPNrTEpH.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 749,                    "dataOriginalPrice": 849,                    "dataProduct": "65\\\" Fire TV Omni 4K QLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/SG34ZWodUkLTxJvMTbjPYR.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 71,                    "dataOriginalPrice": 160,                    "dataProduct": "Saucony Hurricane 24",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/vxf7UD5T2Am7guVzFoFcZ4.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 649,                    "dataOriginalPrice": 749,                    "dataProduct": "Garmin Forerunner 970",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/3GKnEu7CdhtxPMfnPCMCiA.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1049,                    "dataOriginalPrice": 1499,                    "dataProduct": "LG 48\\\" C4 4K OLED TV",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/imvwZV9zoMD6fn9Afuge35.jpg"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 1499,                    "dataOriginalPrice": 2199,                    "dataProduct": "Samsung 49\\\" Odyssey Neo G9 4K Gaming Monitor",                    "dataRetailer": "Amazon",                    "imageURL": "http://cdn.mos.cms.futurecdn.net/XWDEJ5dUAE2nhK8k3Jk7k7.png"                  },                  {                    "dataCurrency": "USD",                    "dataDiscountedPrice": 299,                    "dataOriginalPrice": 699,                    "dataProduct": "EGOHOME Black Memory Foam Mattress (queen)",                    "dataRetailer": "Amazon",                    "imageURL": "https://cdn.mos.cms.futurecdn.net/hMUemtAejNETLVYxNrktzm.jpg"                  }                ]              }            }          };        }        decodeHTML(html) {          if (!html) return '';          const txt = document.createElement("textarea");          txt.innerHTML = String(html);          return txt.value;        }        extractDealData(item) {          const priceRawStr = String(item.price || item.current_price || '0');          const msrpRawStr = String(item.was_price || item.msrp || item.original_price || '0');          const rawPrice = parseFloat(priceRawStr.replace(/[^\d.]/g, '')) || 0;          const rawMsrp = parseFloat(msrpRawStr.replace(/[^\d.]/g, '')) || 0;          const isCheckPrice = rawPrice === 0 || priceRawStr === '0.00' || priceRawStr === '0';                    let originalImageUrl = item.image || item.image_url || item.product_image || '';          let imageUrl = originalImageUrl;          if ((!imageUrl || isCheckPrice) && item.model_image_url) {             imageUrl = item.model_image_url;             originalImageUrl = imageUrl;          } else if ((!imageUrl || isCheckPrice) && item.model_image) {             imageUrl = item.model_image;             originalImageUrl = imageUrl;          }                    if (imageUrl) {            imageUrl = imageUrl.replace(/-(\d+)-(\d+)(\.[a-z.]+)$/i, '$3');          }                    let fallbackImage = '';          if (originalImageUrl && originalImageUrl !== imageUrl) {             fallbackImage = originalImageUrl;          } else if (item.model_image && item.model_image !== imageUrl) {             fallbackImage = item.model_image;          } else if (item.model_image_url && item.model_image_url !== imageUrl) {             fallbackImage = item.model_image_url;          }                    const rawCurrency = item.currency || item.currency_symbol || '$';                    let savingLabel = item.percentage_saving_label || '';          if (!savingLabel && rawMsrp > rawPrice && rawPrice > 0) {            const pct = Math.round(((rawMsrp - rawPrice) / rawMsrp) * 100);            if (pct > 0) {              savingLabel = `${pct}% OFF`;            }          }                    const isPrime = item.shipping && item.shipping.prime === true;                    let scoreRaw = (item.review_score !== undefined && item.review_score !== null && item.review_score > 0) ? parseFloat(item.review_score) : null;          let starRating = 0;          if (scoreRaw !== null) {            starRating = Math.round((scoreRaw > 10 ? scoreRaw / 20 : scoreRaw / 2) * 2) / 2;          }                    return {            id: item.offer_id || item.link || item.url || item.offer_link || Math.random().toString(),            url: item.link || item.url || item.offer_link || '#',            image: imageUrl,            fallbackImage: fallbackImage,            title: item.name || item.title || item.model_name || item.product_name || 'Unknown Product',            brand: item.brand || '',            productName: item.model_name || item.product_name || item.name || '',            merchant: item.merchant_name || item.merchant || item.retailer || 'Retailer',            price: item.price !== undefined ? String(item.price) : '0.00',            currency: this.decodeHTML(rawCurrency),            msrp: item.was_price || item.msrp || item.original_price || null,            rawPrice: rawPrice,            rawMsrp: rawMsrp,            hasWasPrice: (item.was_price !== undefined && item.was_price !== null),            isCheckPrice: isCheckPrice,            savingLabel: savingLabel,            isPrime: isPrime,            starRating: starRating > 0 ? starRating : null,            modelId: item.model_id || '',            productKey: item.product_key || '',            merchantId: (item.merchant && typeof item.merchant === 'object') ? item.merchant.id || '' : '',            matchId: item.match_id || '',            merchantNetwork: (item.merchant && typeof item.merchant === 'object') ? item.merchant.an || '' : '',            merchantUrl: (item.merchant && typeof item.merchant === 'object') ? item.merchant.url || '' : '',            modelBrand: item.model_brand || item.brand || '',            modelParent: item.model_parent || ''          };        }        sortData() {          const sortVal = this.sortSelect ? this.sortSelect.value : (this.getViewMode() === 'savings_squad' ? 'date_desc' : 'discount_desc');          if (sortVal === 'price_asc') {            this.deals.sort((a, b) => a.rawPrice - b.rawPrice);          } else if (sortVal === 'price_desc') {            this.deals.sort((a, b) => b.rawPrice - a.rawPrice);          } else if (sortVal === 'discount_desc') {            this.deals.sort((a, b) => {              const aDiscount = a.rawMsrp > a.rawPrice ? (a.rawMsrp - a.rawPrice) : 0;              const bDiscount = b.rawMsrp > b.rawPrice ? (b.rawMsrp - b.rawPrice) : 0;              return bDiscount - aDiscount;            });          } else if (sortVal === 'date_desc') {             this.deals.sort((a, b) => {                let dateA = 0;                let dateB = 0;                if (a && a.modifiedDate) {                   const valA = Array.isArray(a.modifiedDate) ? a.modifiedDate[0] : a.modifiedDate;                   dateA = new Date(valA).getTime();                   if (isNaN(dateA)) dateA = 0;                }                if (b && b.modifiedDate) {                   const valB = Array.isArray(b.modifiedDate) ? b.modifiedDate[0] : b.modifiedDate;                   dateB = new Date(valB).getTime();                   if (isNaN(dateB)) dateB = 0;                }                return dateB - dateA;             });          }        }        getFilteredDeals() {          let filteredDeals = [...this.deals];                    if (this.dealModeToggle && this.dealModeToggle.checked) {            filteredDeals = filteredDeals.filter(d => d.hasWasPrice || (d.msrp && d.rawMsrp > d.rawPrice));          }                    return filteredDeals;        }        showLoading() {          const _div = '<' + '/div>';          const skeletonCardHtml = `            \x3Cdiv class="tg-df-card">              \x3Cdiv class="tg-df-card-image-box">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-img">${_div}              ${_div}              \x3Cdiv class="tg-df-card-body">                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text title">${_div}                \x3Cdiv class="tg-df-card-footer mt-auto">                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text short" style="height:24px;">${_div}                  \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text" style="height:44px; margin-top:8px;">${_div}                ${_div}              ${_div}            ${_div}`;          this.grid.innerHTML = Array(4).fill(skeletonCardHtml).join('');        }        showError() {          const _div = '<' + '/div>';          this.grid.innerHTML = `\x3Cdiv class="tg-df-message">            An error occurred while finding deals. Please check your connection and try again.          ${_div}`;        }        escapeHTML(str) {          if (!str) return '';          return String(str).replace(/[&<>'"]/g, tag => ({              '&': '&', '<': '<', '>': '>', "'": ''', '"': '"'          }[tag] || tag));        }                bindCouponButtons() {          const btns = this.root.querySelectorAll('.tg-df-tag-coupons');          btns.forEach(btn => {            btn.addEventListener('click', (e) => {              e.preventDefault();              e.stopPropagation();              const merchant = btn.getAttribute('data-merchant');              this.openVouchersModal(merchant);            });          });                    const closeBtn = this.root.querySelector('#tg-df-vouchers-close');          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (closeBtn) {            closeBtn.onclick = () => this.closeVouchersModal();          }          if (backdrop) {            backdrop.onclick = (e) => {              if (e.target === backdrop) this.closeVouchersModal();            };          }        }                closeVouchersModal() {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          if (backdrop) backdrop.classList.remove('active');        }                async checkMerchantsCouponsBulk(merchants) {          if (!merchants || merchants.length === 0) return {};          const controller = new AbortController();          const timeoutId = setTimeout(() => controller.abort(), 4000);          try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchants.join(','));            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '120');            url.searchParams.append('origin', 'widgets-clientside');                        let res; try { res = await fetch(url.toString(), { signal: controller.signal }); } catch (e) { return {}; }            clearTimeout(timeoutId);            if (!res.ok) return {};            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        const foundMerchants = new Set();            offers.forEach(o => {              let mName = o.merchant_name || o.merchant || o.retailer;              if (mName && typeof mName === 'object') mName = mName.name;              if (mName) foundMerchants.add(String(mName).toLowerCase());            });            const resultMap = {};            merchants.forEach(m => {              if (m) resultMap[m] = foundMerchants.has(String(m).toLowerCase());            });            return resultMap;          } catch (e) {            return {};          }        }                async openVouchersModal(merchantName) {          const backdrop = this.root.querySelector('#tg-df-vouchers-modal');          const title = this.root.querySelector('#tg-df-vouchers-title');          const content = this.root.querySelector('#tg-df-vouchers-content');                    if (!backdrop || !content) return;                    // HACK: Hide closing tags          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h4 = '<' + '/h4>';          const _svg = '<' + '/svg>';          const _circle = '<' + '/circle>';          const _polyline = '<' + '/polyline>';          const _rect = '<' + '/rect>';          const _path = '<' + '/path>';                    title.innerText = `${merchantName} Coupons & Deals`;          content.innerHTML = `\x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}                               \x3Cdiv class="tg-df-skeleton tg-df-skeleton-text">${_div}`;          backdrop.classList.add('active');                    try {            const area = this.getAreaCode();            const url = new URL('https://search-api.fie.future.net.uk/widget.php');            url.searchParams.append('model_name', 'Everything');            url.searchParams.append('language', 'en-GB');            if (area) url.searchParams.append('area', area);            url.searchParams.append('combine_product_types', '1');            url.searchParams.append('filter_merchant_name', merchantName);            url.searchParams.append('all_filters', 'false');            url.searchParams.append('exclude_unlabelled', 'false');            url.searchParams.append('include_specs', 'false');            url.searchParams.append('sort', 'voucher');            url.searchParams.append('distinct_merchants', 'natural');            url.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');            url.searchParams.append('rows', '50');            url.searchParams.append('origin', 'widgets-clientside');                        const res = await fetch(url.toString());            if (!res.ok) throw new Error('API Error');            const data = await res.json();                        let offers = [];            if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {              offers = data.widget.data.offers;            } else if (data && data.data && Array.isArray(data.data.offers)) {              offers = data.data.offers;            } else if (Array.isArray(data)) {              offers = data;            } else if (data && Array.isArray(data.offers)) {              offers = data.offers;            } else if (data && data.offers && Array.isArray(data.offers.offer)) {              offers = data.offers.offer;            } else if (data && Array.isArray(data.data)) {              offers = data.data;            }                        if (offers.length === 0) {              content.innerHTML = `\x3Cdiv class="tg-df-message">No vouchers currently available for ${this.escapeHTML(merchantName)}.${_div}`;              return;            }                        content.innerHTML = offers.map((v, idx) => {              let offerObj = v;              if (v.offers && v.offers.offer) {                offerObj = Array.isArray(v.offers.offer) ? v.offers.offer[0] : v.offers.offer;              } else if (v.offer) {                offerObj = Array.isArray(v.offer) ? v.offer[0] : v.offer;              }              let logoUrl = v.logo_url || offerObj.logo_url || '';              if (!logoUrl && v.merchant) {                if (Array.isArray(v.merchant) && v.merchant.length > 0) logoUrl = v.merchant[0].logo_url || '';                else logoUrl = v.merchant.logo_url || '';              }                            const offerName = offerObj.name || offerObj.title || v.name || v.title || 'Special Offer';              const endTime = offerObj.end_time || v.end_time || '';              const linkUrl = offerObj.link || offerObj.url || v.link || v.url || '#';                            let foundVoucherCode = '';              const findVoucherCode = (obj) => {                if (!obj || typeof obj !== 'object') return;                if (obj.type === 'voucher_code' && obj.display_value) {                  foundVoucherCode = obj.display_value;                  return;                }                if (Array.isArray(obj)) {                  for (const item of obj) {                    findVoucherCode(item);                    if (foundVoucherCode) return;                  }                } else {                  for (const k in obj) {                    if (Object.prototype.hasOwnProperty.call(obj, k)) {                      findVoucherCode(obj[k]);                      if (foundVoucherCode) return;                    }                  }                }              };              findVoucherCode(offerObj);              if (!foundVoucherCode) findVoucherCode(v);                            const voucherCode = foundVoucherCode || offerObj.voucher_code || v.voucher_code || '';              const codeHtml = voucherCode ? `\x3Cspan class="tg-df-voucher-code" data-action="copy-code" data-code="${this.escapeHTML(voucherCode)}" title="Copy to clipboard">                \x3Cspan class="tg-df-voucher-code-text">${this.escapeHTML(voucherCode)}${_span}                \x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;flex-shrink:0;" class="tg-df-voucher-copy-icon">                  \x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2">${_rect}                  \x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1">${_path}                ${_svg}              ${_span}` : '';                            const logoHtml = logoUrl                 ? `\x3Cimg src="${this.escapeHTML(logoUrl)}" alt="${this.escapeHTML(offerName)}" class="tg-df-voucher-logo" />`                 : `\x3Cdiv class="tg-df-voucher-logo" style="background:#e2e8f0;">${_div}`;                            let expiryHtml = '';              if (endTime) {                let dStr = endTime;                if (!isNaN(dStr) && String(dStr).length === 10) dStr = Number(dStr) * 1000;                const d = new Date(dStr);                if (!isNaN(d.getTime())) {                  const options = { year: 'numeric', month: 'short', day: 'numeric' };                  expiryHtml = `                    \x3Cdiv class="tg-df-voucher-expiry">                      \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                        \x3Ccircle cx="12" cy="12" r="10">${_circle}                        \x3Cpolyline points="12 6 12 12 16 14">${_polyline}                      ${_svg}                      Expires ${d.toLocaleDateString(undefined, options)}                    ${_div}`;                }              }              const revenueIdVal = generateRevenueId(linkUrl, offerName, merchantName, null);              const rewrittenLinkUrl = rewriteAffiliateLink(linkUrl, area, revenueIdVal);              return `                \x3Ca href="${this.escapeHTML(rewrittenLinkUrl)}" target="_blank" rel="noopener nofollow" class="tg-df-voucher-item"                  data-action="voucher-click"                  data-product-name="${this.escapeHTML(offerName)}"                  data-merchant-name="${this.escapeHTML(merchantName)}"                  data-analytics-id="${this.escapeHTML(offerObj.offer_id || offerObj.id || v.id || '')}"                  data-price=""                  data-previous-price=""                  data-original-link="${this.escapeHTML(linkUrl)}"                  data-revenue-id="${revenueIdVal}"                  data-index="${idx}"                  data-total="${offers.length}"                  data-in-stock="true"                  data-currency="USD"                  data-model-id="${this.escapeHTML(offerObj.model_id || v.model_id || offerObj.id || v.id || '')}"                  data-merchant-id="${this.escapeHTML(offerObj.merchant_id || offerObj.merchant?.id || '')}"                >                  ${logoHtml}                  \x3Cdiv class="tg-df-voucher-content">                    \x3Ch4 class="tg-df-voucher-title">${this.escapeHTML(offerName)}${_h4}                    ${codeHtml}                    ${expiryHtml}                  ${_div}                ${_a}              `;            }).join('');                        // Attach copy functionality            const copyBtns = content.querySelectorAll('[data-action="copy-code"]');            copyBtns.forEach(btn => {              btn.addEventListener('click', async (e) => {                e.preventDefault();                e.stopPropagation();                                const code = btn.getAttribute('data-code');                if (!code) return;                                try {                  const copyToClipboard = async (text) => {                     if (window.navigator.clipboard && window.isSecureContext) {                        try { await window.navigator.clipboard.writeText(text); return; } catch (e) {}                     }                     const textArea = document.createElement("textarea");                     textArea.value = text;                     textArea.style.position = "fixed";                     document.body.appendChild(textArea);                     textArea.focus();                     textArea.select();                     document.execCommand('copy');                     textArea.remove();                  };                  await copyToClipboard(code);                                    // Visual feedback                  btn.classList.add('copied');                  const textSpan = btn.querySelector('.tg-df-voucher-code-text');                  const iconSvg = btn.querySelector('.tg-df-voucher-copy-icon');                                    const origText = textSpan.innerText;                  const origIcon = iconSvg.innerHTML;                                    textSpan.innerText = 'Copied!';                  iconSvg.innerHTML = `\x3Cpolyline points="20 6 9 17 4 12">${_polyline}`;                                    setTimeout(() => {                    if (btn) {                      btn.classList.remove('copied');                      if (textSpan) textSpan.innerText = origText;                      if (iconSvg) iconSvg.innerHTML = origIcon;                    }                  }, 2000);                                    trackElementInteraction({                    id: 'voucher-code-copy',                    name: 'Copy Voucher Code',                    label: `Copied ${code} for ${merchantName}`                  });                } catch (err) {                  console.warn('Failed to copy text: ', err);                }              });            });            // Attach voucher click tracking            const voucherBtns = content.querySelectorAll('[data-action="voucher-click"]');            voucherBtns.forEach(btn => {              btn.addEventListener('click', (e) => {                if (e.target.closest('[data-action="copy-code"]')) return;                                const productName = btn.getAttribute('data-product-name');                const merchantNameAttr = btn.getAttribute('data-merchant-name');                const productId = btn.getAttribute('data-analytics-id');                const price = parseFloat(btn.getAttribute('data-price')) || null;                const prevPriceStr = btn.getAttribute('data-previous-price');                const previousPrice = prevPriceStr ? parseFloat(prevPriceStr) : null;                const originalLink = btn.getAttribute('data-original-link');                const rewrittenLink = btn.getAttribute('href');                const revenueId = btn.getAttribute('data-revenue-id');                const index = parseInt(btn.getAttribute('data-index'), 10) || 0;                const inStock = btn.getAttribute('data-in-stock') === 'true';                const totalText = btn.getAttribute('data-total');                const totalDeals = parseInt(totalText, 10) || 0;                const productCategoryName = 'deals';                const trackingParams = {                  widgetId: this.widgetId,                  productCategoryName: productCategoryName,                  product: {                    modelId: btn.getAttribute('data-model-id') || null,                    matchId: btn.getAttribute('data-match-id') || null,                    brand: btn.getAttribute('data-model-brand') || null,                    parent: btn.getAttribute('data-model-parent') || null,                    name: productName,                    price: price,                    previousPrice: previousPrice,                    link: rewrittenLink,                    originalLink: originalLink,                    inStock: inStock                  },                  zeroBasedProductIndexOrNull: index,                  totalDealsOrProducts: totalDeals,                   merchant: {                    id: btn.getAttribute('data-merchant-id') || null,                    network: btn.getAttribute('data-merchant-network') || null,                    url: btn.getAttribute('data-merchant-url') || null,                    name: merchantNameAttr                  },                  revenueId: revenueId,                  widgetTypeName: this.widgetTypeName,                  isoCurrencyCode: btn.getAttribute('data-currency') || 'USD'                };                if (typeof trackDealClick === 'function') {                  trackDealClick(trackingParams);                }              });            });                                  } catch (e) {            console.warn(e);            content.innerHTML = `\x3Cdiv class="tg-df-message">Failed to load vouchers.${_div}`;          }        }        render() {          try {            if (this.getViewMode() === 'savings_squad' && this.airedaleTags.length > 0) {              if (this.categoryFilterWrapper) {                 this.categoryFilterWrapper.style.display = 'flex';              }              if (this.categoryFilter) {                 const _option = '<' + '/option>';                 let optionsHtml = `\x3Coption value="all">All Categories${_option}`;                 this.airedaleTags.forEach(tag => {                    const isSelected = this.activeDealTag === tag ? 'selected' : '';                    optionsHtml += `\x3Coption value="${this.escapeHTML(tag)}" ${isSelected}>${this.escapeHTML(tag)} (${this.airedaleTagCounts[tag] || 0})${_option}`;                 });                 this.categoryFilter.innerHTML = optionsHtml;                 this.categoryFilter.value = this.activeDealTag || 'all';              }            } else {               if (this.categoryFilterWrapper) {                  this.categoryFilterWrapper.style.display = 'none';               }            }            const displayDeals = this.getFilteredDeals();          // HACK: Hide closing tags from the CMS HTML sanitizer so it doesn't strip them during in-page injection          const _div = '<' + '/div>';          const _span = '<' + '/span>';          const _a = '<' + '/a>';          const _h3 = '<' + '/h3>';          const _p = '<' + '/p>';          const _strong = '<' + '/strong>';          const _sup = '<' + '/sup>';          const _button = '<' + '/button>';          if (displayDeals.length === 0) {            if (this.currentQuery.length > 2 || (this.getViewMode() === 'savings_squad')) {              if (this.deals.length > 0) {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No deals match your selected filters.                ${_div}`;              } else if (this.getViewMode() === 'savings_squad' && this.currentQuery.length <= 2) {                 // Do not show "no exact matches" if query is empty for savings_squad                 this.grid.innerHTML = '';              } else {                 this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                  No exact matches found for "\x3Cstrong>${this.escapeHTML(this.currentQuery)}${_strong}". Try adjusting your search term.                ${_div}`;              }            } else {              this.grid.innerHTML = `\x3Cdiv class="tg-df-message">                Search product or category names to discover the best deals from across the web.              ${_div}`;            }            return;          }          let dealsHtml = displayDeals.slice(0, this.displayLimit).map((deal, index) => {            try {               const currencySym = this.escapeHTML(deal.currency);               const isoCurrencyCode = normalizeCurrency(currencySym);               const escapedPrice = this.escapeHTML(deal.price);               const escapedMsrp = this.escapeHTML(deal.msrp);               const areaCode = this.getAreaCode();                              const revenueId = generateRevenueId(deal.url, deal.title, deal.merchant, null);               const originalLink = deal.url;               const rewrittenLink = rewriteAffiliateLink(deal.url, areaCode, revenueId);                        const productCategoryName = 'deals';            const dataAttr = `              data-action="${deal.isCheckPrice ? 'view-similar-click' : 'deal-click'}"              data-analytics-id="${this.escapeHTML(deal.externalProductId || deal.id || '')}"              data-product-name="${this.escapeHTML(deal.title)}"              data-merchant-name="${this.escapeHTML(deal.merchant)}"              data-price="${deal.rawPrice || ''}"              data-previous-price="${deal.rawMsrp || ''}"              data-original-link="${this.escapeHTML(originalLink)}"              data-revenue-id="${revenueId}"              data-index="${index}"              data-total="${displayDeals.length}"              data-in-stock="${deal.inStock !== false}"              data-currency="${this.escapeHTML(isoCurrencyCode)}"              data-model-id="${this.escapeHTML(deal.modelId || '')}"              data-product-key="${this.escapeHTML(deal.productKey || '')}"              data-merchant-id="${this.escapeHTML(deal.merchantId || '')}"            `;                        let priceGroupHtml = '';            let isSavingsSquadMode = this.getViewMode() === 'savings_squad';            let ctaText = 'View Deal';            let formattedPrice = '';            let msrpHtml = '';                        if (deal.isCheckPrice) {              ctaText = isSavingsSquadMode ? 'View Deal' : 'Check Price';              if (isSavingsSquadMode) {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                  ${_div}                `;              } else {                priceGroupHtml = `                  \x3Cdiv class="tg-df-card-merchant-wrapper">                    \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                  ${_div}                  \x3Cdiv class="tg-df-card-price-group">                    \x3Cspan class="tg-df-card-price" style="font-size: 15px; font-weight: 500; font-style: italic;">See price at retailer${_span}                  ${_div}                `;              }            } else {              // Format Price              formattedPrice = escapedPrice.includes(currencySym)                 ? escapedPrice                 : `${currencySym}${escapedPrice}`;                              // Format MSRP              msrpHtml = deal.msrp && deal.rawMsrp > deal.rawPrice                ? `\x3Cspan class="tg-df-card-msrp">${escapedMsrp.includes(currencySym) ? escapedMsrp : currencySym + escapedMsrp}${_span}`                : '';                              priceGroupHtml = `                \x3Cdiv class="tg-df-card-merchant-wrapper">                  \x3Cspan class="tg-df-card-merchant-pill" title="${this.escapeHTML(deal.merchant)}">${this.escapeHTML(deal.merchant)}${_span}                ${_div}                \x3Cdiv class="tg-df-card-price-group">                  ${isSavingsSquadMode ? '' : `                  \x3Cspan class="tg-df-card-price">${formattedPrice}${_span}                  ${msrpHtml}                  `}                ${_div}              `;            }                        const discountBadgeHtml = deal.savingLabel && !deal.isCheckPrice              ? `\x3Cspan class="tg-df-card-discount-badge">${this.escapeHTML(deal.savingLabel)}${_span}`              : '';                          // HACK for CMS            const _button = '<' + '/button>';            const _svg = '<' + '/svg>';            const _path = '<' + '/path>';            const _rect = '<' + '/rect>';            const _circle = '<' + '/circle>';            const _polyline = '<' + '/polyline>';            const _line = '<' + '/line>';                        let badgesHtml = '';            const primeBadge = deal.isPrime ? `              \x3Cspan class="tg-df-tag tg-df-tag-prime">                \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">                  \x3Cpath d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z">${_path}                ${_svg} Prime              ${_span}            ` : '';                        const couponsBadge = deal.merchant && deal.merchant.toLowerCase().includes('amazon') ? '' : `              \x3Cdiv class="tg-df-coupon-wrapper" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:inline-flex; align-items:center;">                \x3Cdiv class="tg-df-coupon-spinner">${_div}                \x3Cbutton type="button" class="tg-df-tag tg-df-tag-coupons" data-action="coupons-click" data-merchant="${this.escapeHTML(deal.merchant)}" style="display:none;">                  \x3Csvg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">                    \x3Cpath d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z">${_path}                    \x3Cline x1="7" y1="7" x2="7.01" y2="7">${_line}                  ${_svg} Coupons                ${_button}              ${_div}            `;                        // Note: We always add coupons badge if there's a chance, but to allow 3-line titles we check wrapper display state            badgesHtml = `              \x3Cdiv class="tg-df-card-badges">                ${primeBadge}                ${couponsBadge}              ${_div}            `;            const _linearGradient = '<' + '/linearGradient>';            const _polygon = '<' + '/polygon>';            const _stop = '<' + '/stop>';            const _defs = '<' + '/defs>';                        let starHtml = '';            if (deal.starRating) {              let rating = deal.starRating;                            if (rating > 0) {                const fullStars = Math.floor(rating);                const halfStar = (rating - fullStars) >= 0.5 ? 1 : 0;                const emptyStars = Math.max(0, 5 - fullStars - halfStar);                const blue = '#1f69ff'; // Tom's guide brand color from VIEW DEAL button                const gray = '#cbd5e1';                                const starSvgFull = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="${blue}" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                const gradId = 'half_grad_' + Math.floor(Math.random()*1000000);                const starSvgHalf = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" stroke="${blue}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cdefs>\x3ClinearGradient id="${gradId}" x1="0" x2="1" y1="0" y2="0">\x3Cstop offset="50%" stop-color="${blue}">${_stop}\x3Cstop offset="50%" stop-color="transparent">${_stop}${_linearGradient}${_defs}                  \x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26" fill="url(#${gradId})">${_polygon}${_svg}`;                                  const starSvgEmpty = `\x3Csvg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="${gray}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">\x3Cpolygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26">${_polygon}${_svg}`;                                let stars = [];                for (let i=0; i<fullStars; i++) stars.push(starSvgFull);                if (halfStar) stars.push(starSvgHalf);                for (let i=0; i<emptyStars; i++) stars.push(starSvgEmpty);                                starHtml = `\x3Cdiv class="tg-df-card-stars" style="display:flex;align-items:center;margin-bottom:8px;font-size:13px;font-weight:600;color:var(--tg-df-text-muted);">                  \x3Cspan style="margin-right:6px;">Tom's Guide:${_span}                  \x3Cdiv style="display:flex;gap:2px;">                    ${stars.join('')}                  ${_div}                ${_div}`;              }            }            let htmlOutput = '';            if (isSavingsSquadMode) {              htmlOutput += `              \x3Cdiv class="hawk-deal-widget-container tg-df-mobile-only" data-collapsible="true">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''} style="margin-bottom: 10px;">` : ''}                \x3Cdiv class="hawk-deal-widget-wrap">                  \x3Cdiv class="hawk-deal-widget-image-container">                    \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" rel="sponsored noopener" target="_blank" class="hawk-affiliate-link-deal-widget" ${dataAttr}>                      \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="hawk-lazy-image-deal-widget" loading="lazy" width="140" height="160" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                    ${_a}                  ${_div}                  \x3Cdiv class="hawk-deal-widget-text-cta-container">                    \x3Cdiv class="hawk-deal-widget-text-body-container">                      \x3Cdiv class="hawk-deal-widget-text-body-main">                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          ${deal.isCheckPrice ? `                            \x3Cspan class="hawk-deal-widget-title-product-title">${this.escapeHTML(deal.title)}${_span}                          ` : `                            \x3Cspan class="hawk-deal-widget-title-product-title">${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_span}                          `}                        ${_a}                        ${!deal.isCheckPrice && deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan class="hawk-deal-widget-title-was-price">was ${currencySym}${escapedMsrp}${_span}                          ${_a}                        ` : ''}                        \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-container" rel="sponsored noopener" target="_blank" ${dataAttr}>                          \x3Cspan class="hawk-deal-widget-title-retailer-price">                            ${!deal.isCheckPrice ? `                              \x3Cspan class="hawk-deal-widget-title-price">now ${formattedPrice}${_span}                              \x3Cspan class="hawk-deal-widget-title-retailer"> at ${this.escapeHTML(deal.merchant)}${_span}                            ` : `                              \x3Cspan class="hawk-deal-widget-title-price">See price at ${this.escapeHTML(deal.merchant)}${_span}                            `}                          ${_span}                        ${_a}                        ${deal.description ? `\x3Cdiv class="hawk-deal-widget-text-body-description">\x3Cp>${this.escapeHTML(deal.description)}${_p}${_div}` : ''}                      ${_div}                    ${_div}                    \x3Cdiv class="hawk-deal-widget-footer">                      \x3Cdiv class="hawk-deal-widget-button-wrapper">                        \x3Cdiv class="hawk-deal-widget-preferred-partner-wrapper">                          \x3Ca data-google-interstitial="false" aria-label="View ${this.escapeHTML(deal.title)} on ${this.escapeHTML(deal.merchant)}" href="${this.escapeHTML(rewrittenLink)}" class="hawk-affiliate-link-deal-button" rel="sponsored noopener" target="_blank" ${dataAttr}>                            \x3Cspan>${deal.isCheckPrice ? 'Check Price' : 'View Deal'}${_span}                          ${_a}                        ${_div}                      ${_div}                    ${_div}                  ${_div}                ${_div}              ${_div}              `;            }            htmlOutput += `              \x3Cdiv class="tg-df-card ${isSavingsSquadMode ? 'tg-df-desktop-only' : ''}">                ${this.editorMode ? `\x3Cinput type="checkbox" class="tg-df-deal-checkbox" data-id="${this.escapeHTML(deal.id)}" ${this.selectedDeals.has(deal.id) ? 'checked' : ''}>` : ''}                \x3Cdiv class="tg-df-card-image-box">                  ${discountBadgeHtml}                  \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">                    \x3Cimg ${deal.image ? `src="${this.escapeHTML(deal.image)}"` : ''} alt="${this.escapeHTML(deal.title)}" class="tg-df-card-image" loading="lazy" onerror="${deal.fallbackImage ? `if(!this.dataset.fb) { this.dataset.fb='1'; this.src='${this.escapeHTML(deal.fallbackImage)}'; } else { this.style.opacity='0'; }` : `this.style.opacity='0';`}">                  ${_a}                ${_div}                \x3Cdiv class="tg-df-card-body">                  ${starHtml}                  ${badgesHtml}                  \x3Ch3 class="tg-df-card-title tg-df-custom-savings-squad-title" title="${this.escapeHTML(deal.title)}">                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" disable-tracking="true" target="_blank" rel="noopener nofollow" style="text-decoration: none; color: inherit;">                      ${isSavingsSquadMode                         ? (deal.isCheckPrice                             ? (deal.title && deal.title.includes(':')                                 ? `\x3Cstrong>${this.escapeHTML(deal.title.substring(0, deal.title.indexOf(':') + 1))}${_strong}\x3Cspan style="color: #1f69ff; font-weight: normal;">${this.escapeHTML(deal.title.substring(deal.title.indexOf(':') + 1))}${_span}`                                : this.escapeHTML(deal.title)                              )                             : `\x3Cstrong>${deal.brand ? this.escapeHTML(deal.brand) + ' ' : ''}${this.escapeHTML(deal.productName || deal.title || '')}:${_strong} ${deal.rawMsrp && deal.rawMsrp > deal.rawPrice ? `\x3Cspan style="color: #d0021b; text-decoration: line-through; font-weight: normal; margin-right: 4px;">was ${currencySym}${escapedMsrp}${_span} ` : ''}\x3Cspan style="color: #1f69ff; font-weight: normal;">now ${formattedPrice} at ${this.escapeHTML(deal.merchant)}${_span}`                          )                        : this.escapeHTML(deal.title)                      }                    ${_a}                  ${_h3}                  ${deal.description ? `\x3Cp style="font-size: 13px; color: var(--tg-df-text-muted); margin-bottom: 12px; line-height: 1.4;">${this.escapeHTML(deal.description)}${_p}` : ''}                  \x3Cdiv class="tg-df-card-footer">                    ${priceGroupHtml}                    \x3Ca href="${this.escapeHTML(rewrittenLink)}" ${dataAttr} target="_blank" rel="noopener nofollow" class="tg-df-card-cta ${isSavingsSquadMode ? 'tg-df-cta-savings-squad' : ''}" style="text-decoration: none;">${ctaText}${_a}                  ${_div}                ${_div}              ${_div}            `;                        return htmlOutput;            } catch (e) {               console.log("Error rendering deal in map for index", index, typeof deal === 'object' ? JSON.stringify(deal) : deal, "MSG:", e.message);               return '';            }          }).join('');                    if (displayDeals.length > this.displayLimit || ((this.getViewMode() === 'carousel' || this.getViewMode() === 'auto') && displayDeals.length > 0 && displayDeals.length % ((this.rowsSelect && this.rowsSelect.value) ? parseInt(this.rowsSelect.value, 10) : 12) === 0)) {            if (this.getViewMode() === 'carousel') {               dealsHtml += `                 \x3Cbutton type="button" class="tg-df-load-more-card tg-df-load-more">                   \x3Csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-bottom: 8px;">\x3Cpath d="M5 12h14">\x3C/path>\x3Cpath d="m12 5 7 7-7 7">\x3C/path>\x3C/svg>                   Load More                 ${_button}               `;            } else {               dealsHtml += `                 \x3Cdiv style="width: 100%; display: flex; justify-content: center; margin-top: 16px; grid-column: 1 / -1;">                   \x3Cbutton type="button" class="tg-df-tag-outline tg-df-load-more" style="padding: 8px 24px; border-radius: 100px; font-weight: 600; font-size: 14px; cursor: pointer; display: flex; align-items: center;">Load More${_button}                 ${_div}               `;            }          }                    this.grid.innerHTML = dealsHtml;          // Inject JSON-LD          try {            let targetNode = this.hostContainer || document.head;            let jsonLdScript = targetNode.querySelector('#tg-df-json-ld-' + this.widgetId);            if (!jsonLdScript) {                jsonLdScript = document.createElement('script');                jsonLdScript.type = 'application/ld+json';                jsonLdScript.id = 'tg-df-json-ld-' + this.widgetId;                targetNode.appendChild(jsonLdScript);            }            const jsonLdData = {              "@context": "https://schema.org",              "@type": "ItemList",              "itemListElement": displayDeals.slice(0, this.displayLimit).map((deal, index) => {                 let isoCurrency = "USD";                 if (deal.currency === '£') isoCurrency = "GBP";                 else if (deal.currency === '€') isoCurrency = "EUR";                 else if (deal.currency === 'A$') isoCurrency = "AUD";                 else if (deal.currency === 'CA$') isoCurrency = "CAD";                 const areaCode = typeof this.getAreaCode === 'function' ? this.getAreaCode() : 'US';                 const revenueId = typeof generateRevenueId === 'function' ? generateRevenueId(deal.url, deal.title, deal.merchant, null) : '';                 const rewrittenLink = typeof rewriteAffiliateLink === 'function' ? rewriteAffiliateLink(deal.url, areaCode, revenueId) : deal.url;                 return {                   "@type": "ListItem",                   "position": index + 1,                   "item": {                     "@type": "Product",                     "name": deal.title,                     "image": deal.image || "",                     "description": deal.description || "",                     "brand": {                       "@type": "Brand",                       "name": deal.brand || ""                     },                     "offers": {                       "@type": "Offer",                       "priceCurrency": isoCurrency,                       "price": deal.rawPrice || 0,                       "url": rewrittenLink,                       "seller": {                         "@type": "Organization",                         "name": deal.merchant || ""                       }                     }                   }                 };              }).filter(item => item.item.name)            };            jsonLdScript.textContent = JSON.stringify(jsonLdData);          } catch(e) { console.warn("JSON-LD generation failed", e); }                    let gridWrapper = this.grid.parentElement;          if (gridWrapper && gridWrapper.classList.contains('tg-df-grid-wrapper')) {             let rightChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-right');             let leftChevron = gridWrapper.querySelector('.tg-df-carousel-scroll-left');             if (this.getViewMode() === 'carousel') {                 // The observer set up in setupScrollListeners handles visibility.                 if (rightChevron) rightChevron.style.display = 'flex';                 if (leftChevron) leftChevron.style.display = 'none'; // reset correctly             } else {                 if (rightChevron) rightChevron.style.display = 'none';                 if (leftChevron) leftChevron.style.display = 'none';             }          }                    const loadMoreBtn = this.grid.querySelector('.tg-df-load-more');          if (loadMoreBtn) {            loadMoreBtn.addEventListener('click', async () => {              if (typeof trackElementInteraction === 'function') {                trackElementInteraction({ id: 'load-more', name: 'Load more', label: 'Load More Results' });              }              if (displayDeals.length <= this.displayLimit) {                 loadMoreBtn.innerHTML = `                  <svg class="tg-df-spinner" style="width: 16px; height: 16px; display: inline-block; vertical-align: middle; margin-right: 8px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" d="M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48l2.83-2.83"/></svg>                  Loading...                 `;                 loadMoreBtn.disabled = true;                 await this.fetchDeals(this.currentQuery, true);              } else {                 this.displayLimit += this.getRowsLimit();                 this.render();              }            });          }                      this.bindCouponButtons();            this.checkAndUpdateCoupons();                        // Allow hawklinks.js to discover and rewrite our widget links             // by appending the .article-body class and manually triggering processArticle.            let container = this.root.classList.contains('tg-df-container') ? this.root : this.root.querySelector('.tg-df-container');            if (container && !container.classList.contains('article-body')) {               container.classList.add('article-body');            }            setTimeout(() => {               if (this.grid && !this.grid.classList.contains('article-body')) this.grid.classList.add('article-body');               document.dispatchEvent(new CustomEvent('processArticle', { detail: { element: this.root } }));            }, 50);          } catch(e) {            console.warn("Widget render error", e);          }        }                async checkAndUpdateCoupons() {          const wrappers = Array.from(this.root.querySelectorAll('.tg-df-coupon-wrapper'));          if (wrappers.length === 0) return;                    const merchants = [...new Set(wrappers.map(w => w.getAttribute('data-merchant')).filter(Boolean))];          if (merchants.length === 0) return;          const couponResultsMap = await this.checkMerchantsCouponsBulk(merchants);                    for (const merchant of merchants) {            const hasCoupons = !!couponResultsMap[merchant];            const merchantWrappers = wrappers.filter(w => w.getAttribute('data-merchant') === merchant);            merchantWrappers.forEach(wrapper => {              const spinner = wrapper.querySelector('.tg-df-coupon-spinner');              const btn = wrapper.querySelector('.tg-df-tag-coupons');                            if (spinner) spinner.style.display = 'none';                            if (hasCoupons && btn) {                btn.style.display = 'inline-flex';              } else if (!hasCoupons) {                wrapper.style.display = 'none';              }            });          }        }        updateFloatingCopyBar() {          if (!this.editorBar || !this.editorSelectedCount) return;          if (this.editorMode && this.selectedDeals.size > 0) {            this.editorBar.style.display = 'flex';            this.editorSelectedCount.innerText = this.selectedDeals.size;          } else {            this.editorBar.style.display = 'none';          }        }        async copySelectedDealsToCMS() {           function htmlToSlate(htmlString) {              if (!htmlString) return [{ type: 'paragraph', children: [{ text: '' }] }];              let doc;              if (typeof window !== 'undefined' && window.DOMParser) {                 doc = new DOMParser().parseFromString(htmlString, 'text/html');              } else {                 doc = document.implementation.createHTMLDocument('');                 doc.body.innerHTML = htmlString;              }                            function parseNode(node, marks = {}) {                  if (node.nodeType === 3) {                      const text = node.textContent;                      if (!text) return null;                      return { text: text, ...marks };                  }                  if (node.nodeType === 1) {                      const tagName = node.tagName.toLowerCase();                      if (tagName === 'br') {                          return { type: 'line-break', children: [{ text: '' }] };                      }                      if (tagName === 'p') {                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return { type: 'paragraph', children };                      }                      if (tagName === 'strong' || tagName === 'b') {                          const newMarks = { ...marks, bold: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'em' || tagName === 'i') {                          const newMarks = { ...marks, italic: true };                          return Array.from(node.childNodes).map(child => parseNode(child, newMarks)).flat().filter(Boolean);                      }                      if (tagName === 'a') {                          const href = node.getAttribute('href') || '';                          let children = Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                          if (children.length === 0) children.push({ text: "" });                          return {                              type: 'link',                              url: href,                              isNoFollow: (node.getAttribute('rel') || '').includes('nofollow'),                              isSponsored: (node.getAttribute('rel') || '').includes('sponsored'),                              isOpenNewTab: node.getAttribute('target') === '_blank',                              isPreventDataRewrite: false,                              children: children                          };                      }                      return Array.from(node.childNodes).map(child => parseNode(child, marks)).flat().filter(Boolean);                  }                  return null;              }                            let blocksArray = [];              let currentParagraphChildren = [];              function flushParagraph() {                  if (currentParagraphChildren.length > 0) {                      blocksArray.push({ type: 'paragraph', children: currentParagraphChildren });                      currentParagraphChildren = [];                  }              }              Array.from(doc.body.childNodes).forEach(node => {                  const parsed = parseNode(node, {});                  const parsedItems = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : []);                  parsedItems.forEach(item => {                      if (item.type === 'paragraph') {                          flushParagraph();                          blocksArray.push(item);                      } else {                          currentParagraphChildren.push(item);                      }                  });              });              flushParagraph();              if (blocksArray.length === 0) {                  blocksArray = [{ type: 'paragraph', children: [{ text: '' }] }];              }              return blocksArray;           }           const blocks = [];                      this.editorCopyBtn.innerHTML = '\x3Cspan class="tg-df-coupon-spinner" style="display:inline-block; margin-right:8px; border-top-color:#fff;">' + '<' + '/span> Copying...';           for (const deal of Array.from(this.selectedDeals.values())) {              const url = deal.url;              const merchant = deal.merchant;              const title = deal.title;              const image = deal.image;              const currentPrice = deal.currency + deal.rawPrice;              const wasPrice = deal.hasWasPrice && deal.rawMsrp > deal.rawPrice ? deal.currency + deal.rawMsrp : '';                            let couponsChildren = [];              try {                  const area = this.getAreaCode();                  const apiUrl = new URL('https://search-api.fie.future.net.uk/widget.php');                  apiUrl.searchParams.append('model_name', 'Everything');                  apiUrl.searchParams.append('language', 'en-GB');                  apiUrl.searchParams.append('area', area);                  apiUrl.searchParams.append('combine_product_types', '1');                  apiUrl.searchParams.append('filter_merchant_name', merchant);                  apiUrl.searchParams.append('all_filters', 'false');                  apiUrl.searchParams.append('exclude_unlabelled', 'false');                  apiUrl.searchParams.append('include_specs', 'false');                  apiUrl.searchParams.append('sort', 'voucher');                  apiUrl.searchParams.append('distinct_merchants', 'natural');                  apiUrl.searchParams.append('filter_product_types', 'vouchers,offer_deals,newsletter');                  apiUrl.searchParams.append('rows', '3');                  apiUrl.searchParams.append('origin', 'widgets-clientside');                                    let res; try { res = await fetch(apiUrl.toString()); } catch (e) { return; }                  if (res.ok) {                      const data = await res.json();                      let offers = [];                      if (data && data.widget && data.widget.data && Array.isArray(data.widget.data.offers)) {                        offers = data.widget.data.offers;                      } else if (data && data.data && Array.isArray(data.data.offers)) {                        offers = data.data.offers;                      }                                            if (offers.length > 0) {                          couponsChildren.push({ text: "Also check out these coupons: ", bold: true });                          offers.slice(0, 3).forEach((offer, idx) => {                              const actualOffer = offer.offer || offer;                              const offerName = actualOffer.name || actualOffer.title || offer.model_name || offer.title || offer.name || 'Coupon';                              const linkUrl = actualOffer.link || actualOffer.url || actualOffer.offer_link || '#';                              couponsChildren.push({ type: "line-break", children: [{ text: "" }] });                              couponsChildren.push({ text: "🎟️ " });                              couponsChildren.push({                                  type: "link",                                  url: linkUrl,                                  isNoFollow: true,                                  isSponsored: false,                                  isOpenNewTab: true,                                  isPreventDataRewrite: false,                                  children: [{ text: offerName, bold: true }]                              });                          });                      }                  }              } catch (err) {                  console.warn('Failed to fetch coupons for', merchant, err);              }              let descriptionValue = [];              if (deal.text) {                 descriptionValue = htmlToSlate(deal.text);              } else {                 const dealDescriptions = [                   `Don't miss out on this fantastic deal for the ${title}. It is currently available at ${merchant} for a highly competitive price.`,                   `We've spotted an excellent price drop on the ${title}. Grab it now at ${merchant} before it's gone.`,                   `The ${title} is currently seeing a generous discount over at ${merchant}. This is a perfect time to buy if you've been holding out.`,                   `If you're in the market for the ${title}, ${merchant} has just the deal for you.`,                   `Score the ${title} for less at ${merchant} right now. This is a rare chance to save big.`,                   `Upgrade your setup with the ${title}, now available at a stellar price via ${merchant}.`                 ];                 const randomDescription = dealDescriptions[Math.floor(Math.random() * dealDescriptions.length)];                 descriptionValue = [                    { type: "paragraph", children: [{ text: randomDescription }] }                 ];              }                            if (couponsChildren.length > 0) {                 let lastBlock = descriptionValue[descriptionValue.length - 1];                 if (lastBlock && lastBlock.type === 'paragraph') {                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children.push({ text: "Also check out these coupons: ", bold: true });                     lastBlock.children.push({ type: "line-break", children: [{ text: "" }] });                     lastBlock.children = lastBlock.children.concat(couponsChildren);                 } else {                     descriptionValue.push({                         type: "paragraph",                         children: [                             { type: "line-break", children: [{ text: "" }] },                             { type: "line-break", children: [{ text: "" }] },                             { text: "Also check out these coupons: ", bold: true },                             { type: "line-break", children: [{ text: "" }] },                             ...couponsChildren                         ]                     });                 }              }              function normalizeCurrencyToISO(symbol) {                const map = { '£': 'GBP', '$': 'USD', 'A$': 'AUD', 'CA$': 'CAD', '€': 'EUR' };                return map[symbol] || symbol;              }              const isoCurrency = normalizeCurrencyToISO(deal.currency);              blocks.push({                 id: (window.crypto && window.crypto.randomUUID) ? window.crypto.randomUUID() : 'cms-' + Date.now() + Math.random(),                 blockTypeName: "deal",                 excludeFrom: [],                 collapsible: false,                 props: {                    description: {                       value: descriptionValue,                       touched: false,                       validationMessage: ""                    },                    image: {                       value: {                          credit: [{ type: "paragraph", children: [{ text: merchant }] }],                          dateCreated: Date.now(),                          dateModified: Date.now(),                          distribution: [],                          fileSize: 0,                          height: 1000,                          id: deal.id,                          imageRights: "",                          src: image,                          name: title + ".jpg",                          tags: [],                          width: 1000                       },                       touched: false,                       validationMessage: ""                    },                    showDealButton: { value: true, touched: false, validationMessage: "" },                    isPreferredPartner: { value: false, touched: false, validationMessage: "" },                    linkHref: { value: url, touched: false, validationMessage: "" },                    linkLabel: { value: "", touched: false, validationMessage: "" },                    linkIsNoFollow: { value: true, touched: false, validationMessage: "" },                    linkIsSponsored: { value: false, touched: false, validationMessage: "" },                    linkIsOpenNewWindow: { value: true, touched: false, validationMessage: "" },                    customPromoFlags: { value: [], touched: false, validationMessage: "" },                    showStarDeal: { value: false, touched: false, validationMessage: "" },                    savingType: { value: "none", touched: false, validationMessage: "" },                    starDealPromoFlag: { value: "", touched: false, validationMessage: "" },                    showEditorsChoice: { value: false, touched: false, validationMessage: "" },                    editorsChoiceTitle: { value: "", touched: false, validationMessage: "" },                    hawkPriceCurrency: { value: { value: isoCurrency, label: isoCurrency }, touched: false, validationMessage: "" },                    hawkPrice: { value: deal.hasWasPrice ? String(deal.rawMsrp) : String(deal.rawPrice), touched: false, validationMessage: "" },                    hawkSalePrice: { value: String(deal.rawPrice), touched: false, validationMessage: "" },                    lastCheckedPriceDate: { value: "", touched: false, validationMessage: "" },                    hawkModel: { touched: false, validationMessage: "" },                    productId: { value: "", touched: false, validationMessage: "" },                    voucherId: { value: "", touched: false, validationMessage: "" },                    brand: { value: deal.brand || merchant, touched: false, validationMessage: "" },                    productName: { value: title, touched: false, validationMessage: "" },                    label: { value: "", touched: false, validationMessage: "" },                    retailer: { value: merchant, touched: false, validationMessage: "" },                    priceCheckError: false                 },                 failedFetchError: ""              });           }           const payload = {              type: "articleBuilderPages",              data: blocks           };           const jsonStr = JSON.stringify(payload);                      if (navigator.clipboard && navigator.clipboard.writeText) {              navigator.clipboard.writeText(jsonStr).then(() => {                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              }).catch(err => {                 console.warn('Failed to copy text: ', err);                 alert('Failed to copy deals to clipboard. See console.');              });           } else {              // Fallback              const textArea = document.createElement("textarea");              textArea.value = jsonStr;              document.body.appendChild(textArea);              textArea.focus();              textArea.select();              try {                 document.execCommand('copy');                 this.editorCopyBtn.innerHTML = 'Copied!';                 setTimeout(() => {                    this.editorCopyBtn.innerHTML = '\x3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 6px;">\x3Crect x="9" y="9" width="13" height="13" rx="2" ry="2"><' + '/rect>\x3Cpath d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"><' + '/path><' + '/svg> Copy to CMS';                 }, 2000);              } catch (err) {                 console.warn('Fallback: Oops, unable to copy', err);                 alert('Fallback: Failed to copy deals to clipboard.');              }              document.body.removeChild(textArea);           }        }      }      // Initialize the Widget      if (document.readyState === 'loading') {        document.addEventListener('DOMContentLoaded', () => new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer }));      } else {        new DealsFinderWidget({ rootId: 'signal-deals-finder-root', rootNode: shadowRoot, hostContainer: hostContainer });      }    })();  </script></div>
                                                            </article>
                            ]]>
                        </content:encoded>
                                                </item>
            </channel>
</rss>